summaryrefslogtreecommitdiffstats
path: root/gui
diff options
context:
space:
mode:
Diffstat (limited to 'gui')
-rw-r--r--gui/Android.mk181
-rw-r--r--gui/action.cpp1826
-rw-r--r--gui/animation.cpp129
-rw-r--r--gui/blanktimer.cpp123
-rw-r--r--gui/blanktimer.hpp56
-rw-r--r--gui/button.cpp261
-rw-r--r--gui/checkbox.cpp165
-rw-r--r--gui/console.cpp328
-rw-r--r--gui/devices/1080x1920/res/fonts/Roboto-Condensed-40.datbin0 -> 12724 bytes
-rw-r--r--gui/devices/1080x1920/res/images/back-icon.pngbin0 -> 2627 bytes
-rw-r--r--gui/devices/1080x1920/res/images/checkbox_checked.pngbin0 -> 1807 bytes
-rw-r--r--gui/devices/1080x1920/res/images/checkbox_empty.pngbin0 -> 586 bytes
-rw-r--r--gui/devices/1080x1920/res/images/cursor.pngbin0 -> 1452 bytes
-rw-r--r--gui/devices/1080x1920/res/images/curtain.jpgbin0 -> 107182 bytes
-rw-r--r--gui/devices/1080x1920/res/images/file.pngbin0 -> 1267 bytes
-rw-r--r--gui/devices/1080x1920/res/images/folder.pngbin0 -> 1069 bytes
-rw-r--r--gui/devices/1080x1920/res/images/home-icon.pngbin0 -> 2433 bytes
-rw-r--r--gui/devices/1080x1920/res/images/indeterminate001.pngbin0 -> 3791 bytes
-rw-r--r--gui/devices/1080x1920/res/images/indeterminate002.pngbin0 -> 3796 bytes
-rw-r--r--gui/devices/1080x1920/res/images/indeterminate003.pngbin0 -> 3772 bytes
-rw-r--r--gui/devices/1080x1920/res/images/indeterminate004.pngbin0 -> 3760 bytes
-rw-r--r--gui/devices/1080x1920/res/images/indeterminate005.pngbin0 -> 3780 bytes
-rw-r--r--gui/devices/1080x1920/res/images/indeterminate006.pngbin0 -> 3732 bytes
-rw-r--r--gui/devices/1080x1920/res/images/keyboard1.pngbin0 -> 65355 bytes
-rw-r--r--gui/devices/1080x1920/res/images/keyboard2.pngbin0 -> 66480 bytes
-rw-r--r--gui/devices/1080x1920/res/images/keyboard3.pngbin0 -> 57703 bytes
-rw-r--r--gui/devices/1080x1920/res/images/keyboard4.pngbin0 -> 54577 bytes
-rw-r--r--gui/devices/1080x1920/res/images/medium-button.pngbin0 -> 3359 bytes
-rw-r--r--gui/devices/1080x1920/res/images/menu-button.pngbin0 -> 8122 bytes
-rw-r--r--gui/devices/1080x1920/res/images/minus-button.pngbin0 -> 815 bytes
-rw-r--r--gui/devices/1080x1920/res/images/plus-button.pngbin0 -> 1117 bytes
-rw-r--r--gui/devices/1080x1920/res/images/progress_empty.pngbin0 -> 261 bytes
-rw-r--r--gui/devices/1080x1920/res/images/progress_fill.pngbin0 -> 316 bytes
-rw-r--r--gui/devices/1080x1920/res/images/radio_empty.pngbin0 -> 2673 bytes
-rw-r--r--gui/devices/1080x1920/res/images/radio_selected.pngbin0 -> 3432 bytes
-rw-r--r--gui/devices/1080x1920/res/images/slideout.pngbin0 -> 3254 bytes
-rw-r--r--gui/devices/1080x1920/res/images/slider-touch.pngbin0 -> 29925 bytes
-rw-r--r--gui/devices/1080x1920/res/images/slider-used.pngbin0 -> 9123 bytes
-rw-r--r--gui/devices/1080x1920/res/images/slider.pngbin0 -> 21895 bytes
-rw-r--r--gui/devices/1080x1920/res/images/sort-button.pngbin0 -> 1495 bytes
-rw-r--r--gui/devices/1080x1920/res/images/twrplogo.pngbin0 -> 5978 bytes
-rw-r--r--gui/devices/1080x1920/res/images/unlock.pngbin0 -> 68671 bytes
-rw-r--r--gui/devices/1080x1920/res/ui.xml443
-rw-r--r--gui/devices/1920x1200/res/fonts/Roboto-Regular-30.datbin0 -> 8722 bytes
-rw-r--r--gui/devices/1920x1200/res/images/back-icon.pngbin0 -> 1614 bytes
-rw-r--r--gui/devices/1920x1200/res/images/button.pngbin0 -> 3054 bytes
-rw-r--r--gui/devices/1920x1200/res/images/checkbox_checked.pngbin0 -> 1548 bytes
-rw-r--r--gui/devices/1920x1200/res/images/checkbox_empty.pngbin0 -> 440 bytes
-rw-r--r--gui/devices/1920x1200/res/images/console-icon.pngbin0 -> 2198 bytes
-rw-r--r--gui/devices/1920x1200/res/images/console-toggle.pngbin0 -> 2072 bytes
-rw-r--r--gui/devices/1920x1200/res/images/cursor.pngbin0 -> 1452 bytes
-rw-r--r--gui/devices/1920x1200/res/images/curtain.jpgbin0 -> 84783 bytes
-rw-r--r--gui/devices/1920x1200/res/images/file.pngbin0 -> 982 bytes
-rw-r--r--gui/devices/1920x1200/res/images/folder.pngbin0 -> 902 bytes
-rw-r--r--gui/devices/1920x1200/res/images/home-icon.pngbin0 -> 1466 bytes
-rwxr-xr-xgui/devices/1920x1200/res/images/indeterminate001.pngbin0 -> 3791 bytes
-rwxr-xr-xgui/devices/1920x1200/res/images/indeterminate002.pngbin0 -> 3796 bytes
-rwxr-xr-xgui/devices/1920x1200/res/images/indeterminate003.pngbin0 -> 3772 bytes
-rwxr-xr-xgui/devices/1920x1200/res/images/indeterminate004.pngbin0 -> 3760 bytes
-rwxr-xr-xgui/devices/1920x1200/res/images/indeterminate005.pngbin0 -> 3780 bytes
-rwxr-xr-xgui/devices/1920x1200/res/images/indeterminate006.pngbin0 -> 3732 bytes
-rw-r--r--gui/devices/1920x1200/res/images/keyboard1.pngbin0 -> 107358 bytes
-rw-r--r--gui/devices/1920x1200/res/images/keyboard2.pngbin0 -> 115842 bytes
-rw-r--r--gui/devices/1920x1200/res/images/keyboard3.pngbin0 -> 111470 bytes
-rw-r--r--gui/devices/1920x1200/res/images/keyboard4.pngbin0 -> 107902 bytes
-rw-r--r--gui/devices/1920x1200/res/images/medium-button.pngbin0 -> 862 bytes
-rw-r--r--gui/devices/1920x1200/res/images/mediumwide-button.pngbin0 -> 910 bytes
-rw-r--r--gui/devices/1920x1200/res/images/minus-button.pngbin0 -> 635 bytes
-rw-r--r--gui/devices/1920x1200/res/images/plus-button.pngbin0 -> 977 bytes
-rw-r--r--gui/devices/1920x1200/res/images/progress_empty.pngbin0 -> 261 bytes
-rw-r--r--gui/devices/1920x1200/res/images/progress_fill.pngbin0 -> 316 bytes
-rw-r--r--gui/devices/1920x1200/res/images/radio_empty.pngbin0 -> 2673 bytes
-rw-r--r--gui/devices/1920x1200/res/images/radio_selected.pngbin0 -> 3432 bytes
-rw-r--r--gui/devices/1920x1200/res/images/slider-touch.pngbin0 -> 20867 bytes
-rw-r--r--gui/devices/1920x1200/res/images/slider-used.pngbin0 -> 6807 bytes
-rw-r--r--gui/devices/1920x1200/res/images/slider.pngbin0 -> 14723 bytes
-rw-r--r--gui/devices/1920x1200/res/images/sort-button.pngbin0 -> 1033 bytes
-rw-r--r--gui/devices/1920x1200/res/images/twrplogo.pngbin0 -> 4049 bytes
-rw-r--r--gui/devices/1920x1200/res/images/unlock.pngbin0 -> 68671 bytes
-rw-r--r--gui/devices/1920x1200/res/ui.xml456
-rw-r--r--gui/devices/320x320/res/fonts/Roboto-Condensed-14.datbin0 -> 1952 bytes
-rw-r--r--gui/devices/320x320/res/images/back-icon.pngbin0 -> 776 bytes
-rw-r--r--gui/devices/320x320/res/images/checkbox_checked.pngbin0 -> 1114 bytes
-rw-r--r--gui/devices/320x320/res/images/checkbox_empty.pngbin0 -> 343 bytes
-rw-r--r--gui/devices/320x320/res/images/cursor.pngbin0 -> 1452 bytes
-rw-r--r--gui/devices/320x320/res/images/curtain.jpgbin0 -> 20649 bytes
-rw-r--r--gui/devices/320x320/res/images/file.pngbin0 -> 592 bytes
-rw-r--r--gui/devices/320x320/res/images/folder.pngbin0 -> 631 bytes
-rw-r--r--gui/devices/320x320/res/images/home-icon.pngbin0 -> 868 bytes
-rw-r--r--gui/devices/320x320/res/images/indeterminate001.pngbin0 -> 13535 bytes
-rw-r--r--gui/devices/320x320/res/images/indeterminate002.pngbin0 -> 13509 bytes
-rw-r--r--gui/devices/320x320/res/images/indeterminate003.pngbin0 -> 13524 bytes
-rw-r--r--gui/devices/320x320/res/images/indeterminate004.pngbin0 -> 13480 bytes
-rw-r--r--gui/devices/320x320/res/images/indeterminate005.pngbin0 -> 13537 bytes
-rw-r--r--gui/devices/320x320/res/images/indeterminate006.pngbin0 -> 13517 bytes
-rw-r--r--gui/devices/320x320/res/images/keyboard1.pngbin0 -> 16473 bytes
-rw-r--r--gui/devices/320x320/res/images/keyboard2.pngbin0 -> 17608 bytes
-rw-r--r--gui/devices/320x320/res/images/keyboard3.pngbin0 -> 16308 bytes
-rw-r--r--gui/devices/320x320/res/images/keyboard4.pngbin0 -> 15110 bytes
-rw-r--r--gui/devices/320x320/res/images/medium-button.pngbin0 -> 887 bytes
-rw-r--r--gui/devices/320x320/res/images/menu-button.pngbin0 -> 1405 bytes
-rw-r--r--gui/devices/320x320/res/images/minus-button.pngbin0 -> 432 bytes
-rw-r--r--gui/devices/320x320/res/images/plus-button.pngbin0 -> 702 bytes
-rw-r--r--gui/devices/320x320/res/images/progress_empty.pngbin0 -> 219 bytes
-rw-r--r--gui/devices/320x320/res/images/progress_fill.pngbin0 -> 253 bytes
-rw-r--r--gui/devices/320x320/res/images/radio_empty.pngbin0 -> 1454 bytes
-rw-r--r--gui/devices/320x320/res/images/radio_selected.pngbin0 -> 1706 bytes
-rw-r--r--gui/devices/320x320/res/images/slideout.pngbin0 -> 1267 bytes
-rw-r--r--gui/devices/320x320/res/images/slider-touch.pngbin0 -> 5426 bytes
-rw-r--r--gui/devices/320x320/res/images/slider-used.pngbin0 -> 2246 bytes
-rw-r--r--gui/devices/320x320/res/images/slider.pngbin0 -> 3970 bytes
-rw-r--r--gui/devices/320x320/res/images/sort-button.pngbin0 -> 574 bytes
-rw-r--r--gui/devices/320x320/res/images/twrplogo.pngbin0 -> 3154 bytes
-rw-r--r--gui/devices/320x320/res/images/unlock.pngbin0 -> 10461 bytes
-rw-r--r--gui/devices/320x320/res/ui.xml434
-rw-r--r--gui/devices/480x800/res/fonts/Roboto-Regular-20.datbin0 -> 3876 bytes
-rw-r--r--gui/devices/480x800/res/images/back-icon.pngbin0 -> 532 bytes
-rw-r--r--gui/devices/480x800/res/images/checkbox_checked.pngbin0 -> 446 bytes
-rw-r--r--gui/devices/480x800/res/images/checkbox_empty.pngbin0 -> 216 bytes
-rw-r--r--gui/devices/480x800/res/images/cursor.pngbin0 -> 1452 bytes
-rw-r--r--gui/devices/480x800/res/images/curtain.jpgbin0 -> 32644 bytes
-rw-r--r--gui/devices/480x800/res/images/file.pngbin0 -> 287 bytes
-rw-r--r--gui/devices/480x800/res/images/folder.pngbin0 -> 322 bytes
-rw-r--r--gui/devices/480x800/res/images/home-icon.pngbin0 -> 467 bytes
-rw-r--r--gui/devices/480x800/res/images/indeterminate001.pngbin0 -> 1742 bytes
-rw-r--r--gui/devices/480x800/res/images/indeterminate002.pngbin0 -> 1744 bytes
-rw-r--r--gui/devices/480x800/res/images/indeterminate003.pngbin0 -> 1748 bytes
-rw-r--r--gui/devices/480x800/res/images/indeterminate004.pngbin0 -> 1748 bytes
-rw-r--r--gui/devices/480x800/res/images/indeterminate005.pngbin0 -> 1740 bytes
-rw-r--r--gui/devices/480x800/res/images/indeterminate006.pngbin0 -> 1740 bytes
-rw-r--r--gui/devices/480x800/res/images/keyboard1.pngbin0 -> 23278 bytes
-rw-r--r--gui/devices/480x800/res/images/keyboard2.pngbin0 -> 23552 bytes
-rw-r--r--gui/devices/480x800/res/images/keyboard3.pngbin0 -> 21745 bytes
-rw-r--r--gui/devices/480x800/res/images/keyboard4.pngbin0 -> 20998 bytes
-rw-r--r--gui/devices/480x800/res/images/medium-button.pngbin0 -> 653 bytes
-rw-r--r--gui/devices/480x800/res/images/menu-button.pngbin0 -> 1323 bytes
-rw-r--r--gui/devices/480x800/res/images/minus-button.pngbin0 -> 273 bytes
-rw-r--r--gui/devices/480x800/res/images/plus-button.pngbin0 -> 321 bytes
-rw-r--r--gui/devices/480x800/res/images/progress_empty.pngbin0 -> 1004 bytes
-rw-r--r--gui/devices/480x800/res/images/progress_fill.pngbin0 -> 238 bytes
-rw-r--r--gui/devices/480x800/res/images/radio_empty.pngbin0 -> 983 bytes
-rw-r--r--gui/devices/480x800/res/images/radio_selected.pngbin0 -> 1175 bytes
-rw-r--r--gui/devices/480x800/res/images/slideout.pngbin0 -> 649 bytes
-rw-r--r--gui/devices/480x800/res/images/slider-touch.pngbin0 -> 5147 bytes
-rw-r--r--gui/devices/480x800/res/images/slider-used.pngbin0 -> 1659 bytes
-rw-r--r--gui/devices/480x800/res/images/slider.pngbin0 -> 3181 bytes
-rw-r--r--gui/devices/480x800/res/images/sort-button.pngbin0 -> 388 bytes
-rw-r--r--gui/devices/480x800/res/images/twrplogo.pngbin0 -> 4750 bytes
-rw-r--r--gui/devices/480x800/res/images/unlock.pngbin0 -> 22631 bytes
-rw-r--r--gui/devices/480x800/res/ui.xml430
-rw-r--r--gui/devices/800x480/res/fonts/Roboto-Condensed-16.datbin0 -> 2469 bytes
-rw-r--r--gui/devices/800x480/res/images/back-icon.pngbin0 -> 508 bytes
-rw-r--r--gui/devices/800x480/res/images/button.pngbin0 -> 1680 bytes
-rw-r--r--gui/devices/800x480/res/images/checkbox_checked.pngbin0 -> 555 bytes
-rw-r--r--gui/devices/800x480/res/images/checkbox_empty.pngbin0 -> 238 bytes
-rw-r--r--gui/devices/800x480/res/images/console-icon.pngbin0 -> 653 bytes
-rw-r--r--gui/devices/800x480/res/images/console-toggle.pngbin0 -> 649 bytes
-rw-r--r--gui/devices/800x480/res/images/cursor.pngbin0 -> 1452 bytes
-rw-r--r--gui/devices/800x480/res/images/curtain.jpgbin0 -> 24248 bytes
-rw-r--r--gui/devices/800x480/res/images/file.pngbin0 -> 287 bytes
-rw-r--r--gui/devices/800x480/res/images/folder.pngbin0 -> 322 bytes
-rw-r--r--gui/devices/800x480/res/images/home-icon.pngbin0 -> 426 bytes
-rwxr-xr-xgui/devices/800x480/res/images/indeterminate001.pngbin0 -> 1742 bytes
-rwxr-xr-xgui/devices/800x480/res/images/indeterminate002.pngbin0 -> 1744 bytes
-rwxr-xr-xgui/devices/800x480/res/images/indeterminate003.pngbin0 -> 1748 bytes
-rwxr-xr-xgui/devices/800x480/res/images/indeterminate004.pngbin0 -> 1748 bytes
-rwxr-xr-xgui/devices/800x480/res/images/indeterminate005.pngbin0 -> 1740 bytes
-rwxr-xr-xgui/devices/800x480/res/images/indeterminate006.pngbin0 -> 1740 bytes
-rw-r--r--gui/devices/800x480/res/images/keyboard1.pngbin0 -> 22425 bytes
-rw-r--r--gui/devices/800x480/res/images/keyboard2.pngbin0 -> 23869 bytes
-rw-r--r--gui/devices/800x480/res/images/keyboard3.pngbin0 -> 22275 bytes
-rw-r--r--gui/devices/800x480/res/images/keyboard4.pngbin0 -> 20659 bytes
-rw-r--r--gui/devices/800x480/res/images/medium-button.pngbin0 -> 366 bytes
-rw-r--r--gui/devices/800x480/res/images/mediumwide-button.pngbin0 -> 390 bytes
-rw-r--r--gui/devices/800x480/res/images/minus-button.pngbin0 -> 275 bytes
-rw-r--r--gui/devices/800x480/res/images/plus-button.pngbin0 -> 342 bytes
-rw-r--r--gui/devices/800x480/res/images/progress_empty.pngbin0 -> 1004 bytes
-rw-r--r--gui/devices/800x480/res/images/progress_fill.pngbin0 -> 238 bytes
-rw-r--r--gui/devices/800x480/res/images/radio_empty.pngbin0 -> 823 bytes
-rw-r--r--gui/devices/800x480/res/images/radio_selected.pngbin0 -> 1005 bytes
-rw-r--r--gui/devices/800x480/res/images/slider-touch.pngbin0 -> 9427 bytes
-rw-r--r--gui/devices/800x480/res/images/slider-used.pngbin0 -> 3833 bytes
-rw-r--r--gui/devices/800x480/res/images/slider.pngbin0 -> 6393 bytes
-rw-r--r--gui/devices/800x480/res/images/sort-button.pngbin0 -> 406 bytes
-rw-r--r--gui/devices/800x480/res/images/twrplogo.pngbin0 -> 4286 bytes
-rw-r--r--gui/devices/800x480/res/images/unlock.pngbin0 -> 26838 bytes
-rw-r--r--gui/devices/800x480/res/ui.xml465
-rw-r--r--gui/devices/common/res/fonts/DroidSansMono.ttfbin0 -> 108128 bytes
-rw-r--r--gui/devices/common/res/fonts/RobotoCondensed-Regular.ttfbin0 -> 125332 bytes
-rw-r--r--gui/devices/common/res/images/progress_empty.pngbin0 -> 1004 bytes
-rw-r--r--gui/devices/common/res/images/progress_fill.pngbin0 -> 1008 bytes
-rw-r--r--gui/devices/landscape/res/landscape.xml3714
-rw-r--r--gui/devices/portrait/res/portrait.xml3740
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-10.datbin0 -> 1297 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-12.datbin0 -> 1527 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-14.datbin0 -> 1952 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-16.datbin0 -> 2469 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-20.datbin0 -> 3671 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-25.datbin0 -> 5221 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-30.datbin0 -> 7929 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-40.datbin0 -> 12724 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-50.datbin0 -> 20320 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Condensed-60.datbin0 -> 28621 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-10.datbin0 -> 1430 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-12.datbin0 -> 1857 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-14.datbin0 -> 2269 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-16.datbin0 -> 2812 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-20.datbin0 -> 3876 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-25.datbin0 -> 6262 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-30.datbin0 -> 8722 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-40.datbin0 -> 15345 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-50.datbin0 -> 24152 bytes
-rw-r--r--gui/devices/resources/fonts/Roboto-Regular-60.datbin0 -> 34109 bytes
-rw-r--r--gui/devices/watch/res/watch.xml3727
-rw-r--r--gui/fileselector.cpp382
-rw-r--r--gui/fill.cpp52
-rw-r--r--gui/gui.cpp1051
-rw-r--r--gui/gui.h42
-rw-r--r--gui/hardwarekeyboard.cpp416
-rw-r--r--gui/image.cpp92
-rw-r--r--gui/input.cpp713
-rw-r--r--gui/keyboard.cpp571
-rw-r--r--gui/listbox.cpp176
-rw-r--r--gui/mousecursor.cpp147
-rw-r--r--gui/object.cpp210
-rw-r--r--gui/objects.hpp1157
-rw-r--r--gui/pages.cpp1470
-rw-r--r--gui/pages.h7
-rw-r--r--gui/pages.hpp170
-rw-r--r--gui/partitionlist.cpp285
-rw-r--r--gui/patternpassword.cpp318
-rw-r--r--gui/progressbar.cpp226
-rw-r--r--gui/rapidxml.hpp2616
-rw-r--r--gui/remaining.txt4
-rw-r--r--gui/resources.cpp377
-rw-r--r--gui/resources.hpp110
-rw-r--r--gui/scrolllist.cpp609
-rw-r--r--gui/slider.cpp201
-rw-r--r--gui/slidervalue.cpp422
-rw-r--r--gui/text.cpp170
-rw-r--r--gui/twrp0
241 files changed, 28472 insertions, 0 deletions
diff --git a/gui/Android.mk b/gui/Android.mk
new file mode 100644
index 000000000..1fef03d41
--- /dev/null
+++ b/gui/Android.mk
@@ -0,0 +1,181 @@
+LOCAL_PATH := $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_CFLAGS := -fno-strict-aliasing
+
+LOCAL_SRC_FILES := \
+ gui.cpp \
+ resources.cpp \
+ pages.cpp \
+ text.cpp \
+ image.cpp \
+ action.cpp \
+ console.cpp \
+ fill.cpp \
+ button.cpp \
+ checkbox.cpp \
+ fileselector.cpp \
+ progressbar.cpp \
+ animation.cpp \
+ object.cpp \
+ slider.cpp \
+ slidervalue.cpp \
+ listbox.cpp \
+ keyboard.cpp \
+ input.cpp \
+ blanktimer.cpp \
+ partitionlist.cpp \
+ mousecursor.cpp \
+ scrolllist.cpp \
+ patternpassword.cpp
+
+ifneq ($(TWRP_CUSTOM_KEYBOARD),)
+ LOCAL_SRC_FILES += $(TWRP_CUSTOM_KEYBOARD)
+else
+ LOCAL_SRC_FILES += hardwarekeyboard.cpp
+endif
+
+LOCAL_SHARED_LIBRARIES += libminuitwrp libc libstdc++ libminzip libaosprecovery
+LOCAL_MODULE := libguitwrp
+
+#TWRP_EVENT_LOGGING := true
+ifeq ($(TWRP_EVENT_LOGGING), true)
+ LOCAL_CFLAGS += -D_EVENT_LOGGING
+endif
+ifneq ($(TW_USE_KEY_CODE_TOUCH_SYNC),)
+ LOCAL_CFLAGS += -DTW_USE_KEY_CODE_TOUCH_SYNC=$(TW_USE_KEY_CODE_TOUCH_SYNC)
+endif
+
+ifneq ($(TW_NO_SCREEN_BLANK),)
+ LOCAL_CFLAGS += -DTW_NO_SCREEN_BLANK
+endif
+ifneq ($(TW_NO_SCREEN_TIMEOUT),)
+ LOCAL_CFLAGS += -DTW_NO_SCREEN_TIMEOUT
+endif
+ifeq ($(HAVE_SELINUX), true)
+ LOCAL_CFLAGS += -DHAVE_SELINUX
+endif
+ifeq ($(TW_OEM_BUILD), true)
+ LOCAL_CFLAGS += -DTW_OEM_BUILD
+endif
+ifeq ($(TW_DISABLE_TTF), true)
+ LOCAL_CFLAGS += -DTW_DISABLE_TTF
+endif
+ifneq ($(TW_X_OFFSET),)
+ LOCAL_CFLAGS += -DTW_X_OFFSET=$(TW_X_OFFSET)
+endif
+ifneq ($(TW_Y_OFFSET),)
+ LOCAL_CFLAGS += -DTW_Y_OFFSET=$(TW_Y_OFFSET)
+endif
+ifeq ($(TW_ROUND_SCREEN), true)
+ LOCAL_CFLAGS += -DTW_ROUND_SCREEN
+endif
+
+LOCAL_C_INCLUDES += bionic external/stlport/stlport system/core/libpixelflinger/include
+LOCAL_CFLAGS += -DTWRES=\"$(TWRES_PATH)\"
+
+include $(BUILD_STATIC_LIBRARY)
+
+# Transfer in the resources for the device
+include $(CLEAR_VARS)
+LOCAL_MODULE := twrp
+LOCAL_MODULE_TAGS := eng
+LOCAL_MODULE_CLASS := RECOVERY_EXECUTABLES
+LOCAL_MODULE_PATH := $(TARGET_RECOVERY_ROOT_OUT)$(TWRES_PATH)
+TWRP_RES := $(commands_recovery_local_path)/gui/devices/common/res/*
+# enable this to use new themes:
+#TWRP_NEW_THEME := true
+
+ifeq ($(TW_CUSTOM_THEME),)
+ ifeq ($(TW_THEME),)
+ # This converts the old DEVICE_RESOLUTION flag to the new TW_THEME flag
+ PORTRAIT_MDPI := 320x480 480x800 480x854 540x960
+ PORTRAIT_HDPI := 720x1280 800x1280 1080x1920 1200x1920 1440x2560 1600x2560
+ WATCH_MDPI := 240x240 280x280 320x320
+ LANDSCAPE_MDPI := 800x480 1024x600 1024x768
+ LANDSCAPE_HDPI := 1280x800 1920x1200 2560x1600
+ ifneq ($(filter $(DEVICE_RESOLUTION), $(PORTRAIT_MDPI)),)
+ TW_THEME := portrait_mdpi
+ else ifneq ($(filter $(DEVICE_RESOLUTION), $(PORTRAIT_HDPI)),)
+ TW_THEME := portrait_hdpi
+ else ifneq ($(filter $(DEVICE_RESOLUTION), $(WATCH_MDPI)),)
+ TW_THEME := watch_mdpi
+ else ifneq ($(filter $(DEVICE_RESOLUTION), $(LANDSCAPE_MDPI)),)
+ TW_THEME := landscape_mdpi
+ else ifneq ($(filter $(DEVICE_RESOLUTION), $(LANDSCAPE_HDPI)),)
+ TW_THEME := landscape_hdpi
+ endif
+ endif
+ifeq ($(TWRP_NEW_THEME),true)
+ TWRP_THEME_LOC := $(commands_recovery_local_path)/gui/theme/$(TW_THEME)
+ TWRP_RES := $(commands_recovery_local_path)/gui/theme/common/fonts
+ TWRP_RES += $(commands_recovery_local_path)/gui/theme/common/$(word 1,$(subst _, ,$(TW_THEME))).xml
+# for future copying of used include xmls and fonts:
+# UI_XML := $(TWRP_THEME_LOC)/ui.xml
+# TWRP_INCLUDE_XMLS := $(shell xmllint --xpath '/recovery/include/xmlfile/@name' $(UI_XML)|sed -n 's/[^\"]*\"\([^\"]*\)\"[^\"]*/\1\n/gp'|sort|uniq)
+# TWRP_FONTS_TTF := $(shell xmllint --xpath '/recovery/resources/font/@filename' $(UI_XML)|sed -n 's/[^\"]*\"\([^\"]*\)\"[^\"]*/\1\n/gp'|sort|uniq)
+# TWRP_FONTS_DAT := $(shell xmllint --xpath '/recovery/resources/font/@fallback' $(UI_XML)|sed -n 's/[^\"]*\"\([^\"]*\)\"[^\"]*/\1.dat\n/gp'|sort|uniq)
+ifeq ($(wildcard $(TWRP_THEME_LOC)/ui.xml),)
+ $(warning ****************************************************************************)
+ $(warning * TW_THEME is not valid: '$(TW_THEME)')
+ $(warning * Please choose an appropriate TW_THEME or create a new one for your device.)
+ $(warning * Available themes:)
+ $(warning * $(notdir $(wildcard $(commands_recovery_local_path)/gui/theme/*_*)))
+ $(warning ****************************************************************************)
+ $(error stopping)
+endif
+else
+ TWRP_RES += $(commands_recovery_local_path)/gui/devices/$(word 1,$(subst _, ,$(TW_THEME)))/res/*
+ ifeq ($(TW_THEME), portrait_mdpi)
+ TWRP_THEME_LOC := $(commands_recovery_local_path)/gui/devices/480x800/res
+ else ifeq ($(TW_THEME), portrait_hdpi)
+ TWRP_THEME_LOC := $(commands_recovery_local_path)/gui/devices/1080x1920/res
+ else ifeq ($(TW_THEME), watch_mdpi)
+ TWRP_THEME_LOC := $(commands_recovery_local_path)/gui/devices/320x320/res
+ else ifeq ($(TW_THEME), landscape_mdpi)
+ TWRP_THEME_LOC := $(commands_recovery_local_path)/gui/devices/800x480/res
+ else ifeq ($(TW_THEME), landscape_hdpi)
+ TWRP_THEME_LOC := $(commands_recovery_local_path)/gui/devices/1920x1200/res
+ else
+ $(warning ****************************************************************************)
+ $(warning * TW_THEME ($(TW_THEME)) is not valid.)
+ $(warning * Please choose an appropriate TW_THEME or create a new one for your device.)
+ $(warning * Valid options are portrait_mdpi portrait_hdpi watch_mdpi)
+ $(warning * landscape_mdpi landscape_hdpi)
+ $(warning ****************************************************************************)
+ $(error stopping)
+ endif
+endif
+else
+ TWRP_THEME_LOC := $(TW_CUSTOM_THEME)
+endif
+
+ifeq ($(TW_DISABLE_TTF), true)
+ TWRP_REMOVE_FONT := rm -f $(TARGET_RECOVERY_ROOT_OUT)$(TWRES_PATH)fonts/*.ttf
+else
+ TWRP_REMOVE_FONT := rm -f $(TARGET_RECOVERY_ROOT_OUT)$(TWRES_PATH)fonts/*.dat
+endif
+
+TWRP_RES_GEN := $(intermediates)/twrp
+ifneq ($(TW_USE_TOOLBOX), true)
+ TWRP_SH_TARGET := /sbin/busybox
+else
+ TWRP_SH_TARGET := /sbin/mksh
+endif
+
+$(TWRP_RES_GEN):
+ mkdir -p $(TARGET_RECOVERY_ROOT_OUT)$(TWRES_PATH)
+ cp -fr $(TWRP_RES) $(TARGET_RECOVERY_ROOT_OUT)$(TWRES_PATH)
+ cp -fr $(TWRP_THEME_LOC)/* $(TARGET_RECOVERY_ROOT_OUT)$(TWRES_PATH)
+ $(TWRP_REMOVE_FONT)
+ mkdir -p $(TARGET_RECOVERY_ROOT_OUT)/sbin/
+ifneq ($(TW_USE_TOOLBOX), true)
+ ln -sf $(TWRP_SH_TARGET) $(TARGET_RECOVERY_ROOT_OUT)/sbin/sh
+endif
+ ln -sf /sbin/pigz $(TARGET_RECOVERY_ROOT_OUT)/sbin/gzip
+ ln -sf /sbin/unpigz $(TARGET_RECOVERY_ROOT_OUT)/sbin/gunzip
+
+
+LOCAL_GENERATED_SOURCES := $(TWRP_RES_GEN)
+LOCAL_SRC_FILES := twrp $(TWRP_RES_GEN)
+include $(BUILD_PREBUILT)
diff --git a/gui/action.cpp b/gui/action.cpp
new file mode 100644
index 000000000..0f8c7eea6
--- /dev/null
+++ b/gui/action.cpp
@@ -0,0 +1,1826 @@
+/*update
+ Copyright 2013 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <linux/input.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <sys/wait.h>
+#include <dirent.h>
+#include <pwd.h>
+
+#include <string>
+#include <sstream>
+#include "../partitions.hpp"
+#include "../twrp-functions.hpp"
+#include "../openrecoveryscript.hpp"
+
+#include "../adb_install.h"
+#include "../fuse_sideload.h"
+#include "blanktimer.hpp"
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+#include "../variables.h"
+#include "../twinstall.h"
+#include "cutils/properties.h"
+#include "../adb_install.h"
+#include "../set_metadata.h"
+};
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../tw_atomic.hpp"
+
+void curtainClose(void);
+
+GUIAction::mapFunc GUIAction::mf;
+std::set<string> GUIAction::setActionsRunningInCallerThread;
+static string zip_queue[10];
+static int zip_queue_index;
+static pthread_t terminal_command;
+pid_t sideload_child_pid;
+
+static void *ActionThread_work_wrapper(void *data);
+
+class ActionThread
+{
+public:
+ ActionThread();
+ ~ActionThread();
+
+ void threadActions(GUIAction *act);
+ void run(void *data);
+private:
+ friend void *ActionThread_work_wrapper(void*);
+ struct ThreadData
+ {
+ ActionThread *this_;
+ GUIAction *act;
+ ThreadData(ActionThread *this_, GUIAction *act) : this_(this_), act(act) {}
+ };
+
+ pthread_t m_thread;
+ bool m_thread_running;
+ pthread_mutex_t m_act_lock;
+};
+
+static ActionThread action_thread; // for all kinds of longer running actions
+static ActionThread cancel_thread; // for longer running "cancel" actions
+
+static void *ActionThread_work_wrapper(void *data)
+{
+ static_cast<ActionThread::ThreadData*>(data)->this_->run(data);
+ return NULL;
+}
+
+ActionThread::ActionThread()
+{
+ m_thread_running = false;
+ pthread_mutex_init(&m_act_lock, NULL);
+}
+
+ActionThread::~ActionThread()
+{
+ pthread_mutex_lock(&m_act_lock);
+ if(m_thread_running) {
+ pthread_mutex_unlock(&m_act_lock);
+ pthread_join(m_thread, NULL);
+ } else {
+ pthread_mutex_unlock(&m_act_lock);
+ }
+ pthread_mutex_destroy(&m_act_lock);
+}
+
+void ActionThread::threadActions(GUIAction *act)
+{
+ pthread_mutex_lock(&m_act_lock);
+ if (m_thread_running) {
+ pthread_mutex_unlock(&m_act_lock);
+ LOGERR("Another threaded action is already running -- not running %u actions starting with '%s'\n",
+ act->mActions.size(), act->mActions[0].mFunction.c_str());
+ } else {
+ m_thread_running = true;
+ pthread_mutex_unlock(&m_act_lock);
+ ThreadData *d = new ThreadData(this, act);
+ pthread_create(&m_thread, NULL, &ActionThread_work_wrapper, d);
+ }
+}
+
+void ActionThread::run(void *data)
+{
+ ThreadData *d = (ThreadData*)data;
+ GUIAction* act = d->act;
+
+ std::vector<GUIAction::Action>::iterator it;
+ for (it = act->mActions.begin(); it != act->mActions.end(); ++it)
+ act->doAction(*it);
+
+ pthread_mutex_lock(&m_act_lock);
+ m_thread_running = false;
+ pthread_mutex_unlock(&m_act_lock);
+ delete d;
+}
+
+GUIAction::GUIAction(xml_node<>* node)
+ : GUIObject(node)
+{
+ xml_node<>* child;
+ xml_node<>* actions;
+ xml_attribute<>* attr;
+
+ if (!node) return;
+
+ if (mf.empty()) {
+#define ADD_ACTION(n) mf[#n] = &GUIAction::n
+#define ADD_ACTION_EX(name, func) mf[name] = &GUIAction::func
+ // These actions will be run in the caller's thread
+ ADD_ACTION(reboot);
+ ADD_ACTION(home);
+ ADD_ACTION(key);
+ ADD_ACTION(page);
+ ADD_ACTION(reload);
+ ADD_ACTION(readBackup);
+ ADD_ACTION(set);
+ ADD_ACTION(clear);
+ ADD_ACTION(mount);
+ ADD_ACTION(unmount);
+ ADD_ACTION_EX("umount", unmount);
+ ADD_ACTION(restoredefaultsettings);
+ ADD_ACTION(copylog);
+ ADD_ACTION(compute);
+ ADD_ACTION_EX("addsubtract", compute);
+ ADD_ACTION(setguitimezone);
+ ADD_ACTION(overlay);
+ ADD_ACTION(queuezip);
+ ADD_ACTION(cancelzip);
+ ADD_ACTION(queueclear);
+ ADD_ACTION(sleep);
+ ADD_ACTION(appenddatetobackupname);
+ ADD_ACTION(generatebackupname);
+ ADD_ACTION(checkpartitionlist);
+ ADD_ACTION(getpartitiondetails);
+ ADD_ACTION(screenshot);
+ ADD_ACTION(setbrightness);
+ ADD_ACTION(fileexists);
+ ADD_ACTION(killterminal);
+ ADD_ACTION(checkbackupname);
+ ADD_ACTION(adbsideloadcancel);
+ ADD_ACTION(fixsu);
+ ADD_ACTION(startmtp);
+ ADD_ACTION(stopmtp);
+ ADD_ACTION(cancelbackup);
+ ADD_ACTION(checkpartitionlifetimewrites);
+ ADD_ACTION(mountsystemtoggle);
+
+ // remember actions that run in the caller thread
+ for (mapFunc::const_iterator it = mf.begin(); it != mf.end(); ++it)
+ setActionsRunningInCallerThread.insert(it->first);
+
+ // These actions will run in a separate thread
+ ADD_ACTION(flash);
+ ADD_ACTION(wipe);
+ ADD_ACTION(refreshsizes);
+ ADD_ACTION(nandroid);
+ ADD_ACTION(fixpermissions);
+ ADD_ACTION(dd);
+ ADD_ACTION(partitionsd);
+ ADD_ACTION(installhtcdumlock);
+ ADD_ACTION(htcdumlockrestoreboot);
+ ADD_ACTION(htcdumlockreflashrecovery);
+ ADD_ACTION(cmd);
+ ADD_ACTION(terminalcommand);
+ ADD_ACTION(reinjecttwrp);
+ ADD_ACTION(decrypt);
+ ADD_ACTION(adbsideload);
+ ADD_ACTION(openrecoveryscript);
+ ADD_ACTION(installsu);
+ ADD_ACTION(decrypt_backup);
+ ADD_ACTION(repair);
+ ADD_ACTION(resize);
+ ADD_ACTION(changefilesystem);
+ ADD_ACTION(flashimage);
+ }
+
+ // First, get the action
+ actions = FindNode(node, "actions");
+ if (actions) child = FindNode(actions, "action");
+ else child = FindNode(node, "action");
+
+ if (!child) return;
+
+ while (child)
+ {
+ Action action;
+
+ attr = child->first_attribute("function");
+ if (!attr) return;
+
+ action.mFunction = attr->value();
+ action.mArg = child->value();
+ mActions.push_back(action);
+
+ child = child->next_sibling("action");
+ }
+
+ // Now, let's get either the key or region
+ child = FindNode(node, "touch");
+ if (child)
+ {
+ attr = child->first_attribute("key");
+ if (attr)
+ {
+ std::vector<std::string> keys = TWFunc::Split_String(attr->value(), "+");
+ for(size_t i = 0; i < keys.size(); ++i)
+ {
+ const int key = getKeyByName(keys[i]);
+ mKeys[key] = false;
+ }
+ }
+ else
+ {
+ attr = child->first_attribute("x");
+ if (!attr) return;
+ mActionX = atol(attr->value());
+ attr = child->first_attribute("y");
+ if (!attr) return;
+ mActionY = atol(attr->value());
+ attr = child->first_attribute("w");
+ if (!attr) return;
+ mActionW = atol(attr->value());
+ attr = child->first_attribute("h");
+ if (!attr) return;
+ mActionH = atol(attr->value());
+ }
+ }
+}
+
+int GUIAction::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if (state == TOUCH_RELEASE)
+ doActions();
+
+ return 0;
+}
+
+int GUIAction::NotifyKey(int key, bool down)
+{
+ if (mKeys.empty())
+ return 0;
+
+ std::map<int, bool>::iterator itr = mKeys.find(key);
+ if(itr == mKeys.end())
+ return 0;
+
+ bool prevState = itr->second;
+ itr->second = down;
+
+ // If there is only one key for this action, wait for key up so it
+ // doesn't trigger with multi-key actions.
+ // Else, check if all buttons are pressed, then consume their release events
+ // so they don't trigger one-button actions and reset mKeys pressed status
+ if(mKeys.size() == 1) {
+ if(!down && prevState)
+ doActions();
+ } else if(down) {
+ for(itr = mKeys.begin(); itr != mKeys.end(); ++itr) {
+ if(!itr->second)
+ return 0;
+ }
+
+ // Passed, all req buttons are pressed, reset them and consume release events
+ HardwareKeyboard *kb = PageManager::GetHardwareKeyboard();
+ for(itr = mKeys.begin(); itr != mKeys.end(); ++itr) {
+ kb->ConsumeKeyRelease(itr->first);
+ itr->second = false;
+ }
+
+ doActions();
+ }
+
+ return 0;
+}
+
+int GUIAction::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIObject::NotifyVarChange(varName, value);
+
+ if (varName.empty() && !isConditionValid() && mKeys.empty() && !mActionW)
+ doActions();
+ else if((varName.empty() || IsConditionVariable(varName)) && isConditionValid() && isConditionTrue())
+ doActions();
+
+ return 0;
+}
+
+void GUIAction::simulate_progress_bar(void)
+{
+ gui_print("Simulating actions...\n");
+ for (int i = 0; i < 5; i++)
+ {
+ if (PartitionManager.stop_backup.get_value()) {
+ DataManager::SetValue("tw_cancel_backup", 1);
+ gui_print("Backup Canceled.\n");
+ DataManager::SetValue("ui_progress", 0);
+ PartitionManager.stop_backup.set_value(0);
+ return;
+ }
+ usleep(500000);
+ DataManager::SetValue("ui_progress", i * 20);
+ }
+}
+
+int GUIAction::flash_zip(std::string filename, int* wipe_cache)
+{
+ int ret_val = 0;
+
+ DataManager::SetValue("ui_progress", 0);
+
+ if (filename.empty())
+ {
+ LOGERR("No file specified.\n");
+ return -1;
+ }
+
+ if (!PartitionManager.Mount_By_Path(filename, true))
+ return -1;
+
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ ret_val = TWinstall_zip(filename.c_str(), wipe_cache);
+
+ // Now, check if we need to ensure TWRP remains installed...
+ struct stat st;
+ if (stat("/sbin/installTwrp", &st) == 0)
+ {
+ DataManager::SetValue("tw_operation", "Configuring TWRP");
+ DataManager::SetValue("tw_partition", "");
+ gui_print("Configuring TWRP...\n");
+ if (TWFunc::Exec_Cmd("/sbin/installTwrp reinstall") < 0)
+ {
+ gui_print("Unable to configure TWRP with this kernel.\n");
+ }
+ }
+ }
+
+ // Done
+ DataManager::SetValue("ui_progress", 100);
+ DataManager::SetValue("ui_progress", 0);
+ return ret_val;
+}
+
+GUIAction::ThreadType GUIAction::getThreadType(const GUIAction::Action& action)
+{
+ string func = gui_parse_text(action.mFunction);
+ bool needsThread = setActionsRunningInCallerThread.find(func) == setActionsRunningInCallerThread.end();
+ if (needsThread) {
+ if (func == "cancelbackup")
+ return THREAD_CANCEL;
+ else
+ return THREAD_ACTION;
+ }
+ return THREAD_NONE;
+}
+
+int GUIAction::doActions()
+{
+ if (mActions.size() < 1)
+ return -1;
+
+ // Determine in which thread to run the actions.
+ // Do it for all actions at once before starting, so that we can cancel the whole batch if the thread is already busy.
+ ThreadType threadType = THREAD_NONE;
+ std::vector<Action>::iterator it;
+ for (it = mActions.begin(); it != mActions.end(); ++it) {
+ ThreadType tt = getThreadType(*it);
+ if (tt == THREAD_NONE)
+ continue;
+ if (threadType == THREAD_NONE)
+ threadType = tt;
+ else if (threadType != tt) {
+ LOGERR("Can't mix normal and cancel actions in the same list.\n"
+ "Running the whole batch in the cancel thread.\n");
+ threadType = THREAD_CANCEL;
+ break;
+ }
+ }
+
+ // Now run the actions in the desired thread.
+ switch (threadType) {
+ case THREAD_ACTION:
+ action_thread.threadActions(this);
+ break;
+
+ case THREAD_CANCEL:
+ cancel_thread.threadActions(this);
+ break;
+
+ default: {
+ // no iterators here because theme reloading might kill our object
+ const size_t cnt = mActions.size();
+ for (size_t i = 0; i < cnt; ++i)
+ doAction(mActions[i]);
+ }
+ }
+
+ return 0;
+}
+
+int GUIAction::doAction(Action action)
+{
+ DataManager::GetValue(TW_SIMULATE_ACTIONS, simulate);
+
+ std::string function = gui_parse_text(action.mFunction);
+ std::string arg = gui_parse_text(action.mArg);
+
+ // find function and execute it
+ mapFunc::const_iterator funcitr = mf.find(function);
+ if (funcitr != mf.end())
+ return (this->*funcitr->second)(arg);
+
+ LOGERR("Unknown action '%s'\n", function.c_str());
+ return -1;
+}
+
+void GUIAction::operation_start(const string operation_name)
+{
+ LOGINFO("operation_start: '%s'\n", operation_name.c_str());
+ time(&Start);
+ DataManager::SetValue(TW_ACTION_BUSY, 1);
+ DataManager::SetValue("ui_progress", 0);
+ DataManager::SetValue("tw_operation", operation_name);
+ DataManager::SetValue("tw_operation_state", 0);
+ DataManager::SetValue("tw_operation_status", 0);
+}
+
+void GUIAction::operation_end(const int operation_status)
+{
+ time_t Stop;
+ int simulate_fail;
+ DataManager::SetValue("ui_progress", 100);
+ if (simulate) {
+ DataManager::GetValue(TW_SIMULATE_FAIL, simulate_fail);
+ if (simulate_fail != 0)
+ DataManager::SetValue("tw_operation_status", 1);
+ else
+ DataManager::SetValue("tw_operation_status", 0);
+ } else {
+ if (operation_status != 0) {
+ DataManager::SetValue("tw_operation_status", 1);
+ }
+ else {
+ DataManager::SetValue("tw_operation_status", 0);
+ }
+ }
+ DataManager::SetValue("tw_operation_state", 1);
+ DataManager::SetValue(TW_ACTION_BUSY, 0);
+ blankTimer.resetTimerAndUnblank();
+ time(&Stop);
+ if ((int) difftime(Stop, Start) > 10)
+ DataManager::Vibrate("tw_action_vibrate");
+ LOGINFO("operation_end - status=%d\n", operation_status);
+}
+
+int GUIAction::reboot(std::string arg)
+{
+ //curtainClose(); this sometimes causes a crash
+
+ sync();
+ DataManager::SetValue("tw_gui_done", 1);
+ DataManager::SetValue("tw_reboot_arg", arg);
+
+ return 0;
+}
+
+int GUIAction::home(std::string arg)
+{
+ PageManager::SelectPackage("TWRP");
+ gui_changePage("main");
+ return 0;
+}
+
+int GUIAction::key(std::string arg)
+{
+ const int key = getKeyByName(arg);
+ PageManager::NotifyKey(key, true);
+ PageManager::NotifyKey(key, false);
+ return 0;
+}
+
+int GUIAction::page(std::string arg)
+{
+ std::string page_name = gui_parse_text(arg);
+ return gui_changePage(page_name);
+}
+
+int GUIAction::reload(std::string arg)
+{
+ int check = 0, ret_val = 0;
+ std::string theme_path;
+
+ theme_path = DataManager::GetSettingsStoragePath();
+ if (PartitionManager.Mount_By_Path(theme_path.c_str(), 1) < 0) {
+ LOGERR("Unable to mount %s during reload function startup.\n", theme_path.c_str());
+ check = 1;
+ }
+
+ theme_path += "/TWRP/theme/ui.zip";
+ if (check != 0 || PageManager::ReloadPackage("TWRP", theme_path) != 0)
+ {
+ // Loading the custom theme failed - try loading the stock theme
+ LOGINFO("Attempting to reload stock theme...\n");
+ if (PageManager::ReloadPackage("TWRP", TWRES "ui.xml"))
+ {
+ LOGERR("Failed to load base packages.\n");
+ ret_val = 1;
+ }
+ }
+ return 0;
+}
+
+int GUIAction::readBackup(std::string arg)
+{
+ string Restore_Name;
+ DataManager::GetValue("tw_restore", Restore_Name);
+ PartitionManager.Set_Restore_Files(Restore_Name);
+ return 0;
+}
+
+int GUIAction::set(std::string arg)
+{
+ if (arg.find('=') != string::npos)
+ {
+ string varName = arg.substr(0, arg.find('='));
+ string value = arg.substr(arg.find('=') + 1, string::npos);
+
+ DataManager::GetValue(value, value);
+ DataManager::SetValue(varName, value);
+ }
+ else
+ DataManager::SetValue(arg, "1");
+ return 0;
+}
+
+int GUIAction::clear(std::string arg)
+{
+ DataManager::SetValue(arg, "0");
+ return 0;
+}
+
+int GUIAction::mount(std::string arg)
+{
+ if (arg == "usb") {
+ DataManager::SetValue(TW_ACTION_BUSY, 1);
+ if (!simulate)
+ PartitionManager.usb_storage_enable();
+ else
+ gui_print("Simulating actions...\n");
+ } else if (!simulate) {
+ PartitionManager.Mount_By_Path(arg, true);
+ PartitionManager.Add_MTP_Storage(arg);
+ } else
+ gui_print("Simulating actions...\n");
+ return 0;
+}
+
+int GUIAction::unmount(std::string arg)
+{
+ if (arg == "usb") {
+ if (!simulate)
+ PartitionManager.usb_storage_disable();
+ else
+ gui_print("Simulating actions...\n");
+ DataManager::SetValue(TW_ACTION_BUSY, 0);
+ } else if (!simulate) {
+ PartitionManager.UnMount_By_Path(arg, true);
+ } else
+ gui_print("Simulating actions...\n");
+ return 0;
+}
+
+int GUIAction::restoredefaultsettings(std::string arg)
+{
+ operation_start("Restore Defaults");
+ if (simulate) // Simulated so that people don't accidently wipe out the "simulation is on" setting
+ gui_print("Simulating actions...\n");
+ else {
+ DataManager::ResetDefaults();
+ PartitionManager.Update_System_Details();
+ PartitionManager.Mount_Current_Storage(true);
+ }
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::copylog(std::string arg)
+{
+ operation_start("Copy Log");
+ if (!simulate)
+ {
+ string dst;
+ PartitionManager.Mount_Current_Storage(true);
+ dst = DataManager::GetCurrentStoragePath() + "/recovery.log";
+ TWFunc::copy_file("/tmp/recovery.log", dst.c_str(), 0755);
+ tw_set_default_metadata(dst.c_str());
+ sync();
+ gui_print("Copied recovery log to %s.\n", DataManager::GetCurrentStoragePath().c_str());
+ } else
+ simulate_progress_bar();
+ operation_end(0);
+ return 0;
+}
+
+
+int GUIAction::compute(std::string arg)
+{
+ if (arg.find("+") != string::npos)
+ {
+ string varName = arg.substr(0, arg.find('+'));
+ string string_to_add = arg.substr(arg.find('+') + 1, string::npos);
+ int amount_to_add = atoi(string_to_add.c_str());
+ int value;
+
+ DataManager::GetValue(varName, value);
+ DataManager::SetValue(varName, value + amount_to_add);
+ return 0;
+ }
+ if (arg.find("-") != string::npos)
+ {
+ string varName = arg.substr(0, arg.find('-'));
+ string string_to_subtract = arg.substr(arg.find('-') + 1, string::npos);
+ int amount_to_subtract = atoi(string_to_subtract.c_str());
+ int value;
+
+ DataManager::GetValue(varName, value);
+ value -= amount_to_subtract;
+ if (value <= 0)
+ value = 0;
+ DataManager::SetValue(varName, value);
+ return 0;
+ }
+ if (arg.find("*") != string::npos)
+ {
+ string varName = arg.substr(0, arg.find('*'));
+ string multiply_by_str = gui_parse_text(arg.substr(arg.find('*') + 1, string::npos));
+ int multiply_by = atoi(multiply_by_str.c_str());
+ int value;
+
+ DataManager::GetValue(varName, value);
+ DataManager::SetValue(varName, value*multiply_by);
+ return 0;
+ }
+ if (arg.find("/") != string::npos)
+ {
+ string varName = arg.substr(0, arg.find('/'));
+ string divide_by_str = gui_parse_text(arg.substr(arg.find('/') + 1, string::npos));
+ int divide_by = atoi(divide_by_str.c_str());
+ int value;
+
+ if(divide_by != 0)
+ {
+ DataManager::GetValue(varName, value);
+ DataManager::SetValue(varName, value/divide_by);
+ }
+ return 0;
+ }
+ LOGERR("Unable to perform compute '%s'\n", arg.c_str());
+ return -1;
+}
+
+int GUIAction::setguitimezone(std::string arg)
+{
+ string SelectedZone;
+ DataManager::GetValue(TW_TIME_ZONE_GUISEL, SelectedZone); // read the selected time zone into SelectedZone
+ string Zone = SelectedZone.substr(0, SelectedZone.find(';')); // parse to get time zone
+ string DSTZone = SelectedZone.substr(SelectedZone.find(';') + 1, string::npos); // parse to get DST component
+
+ int dst;
+ DataManager::GetValue(TW_TIME_ZONE_GUIDST, dst); // check wether user chose to use DST
+
+ string offset;
+ DataManager::GetValue(TW_TIME_ZONE_GUIOFFSET, offset); // pull in offset
+
+ string NewTimeZone = Zone;
+ if (offset != "0")
+ NewTimeZone += ":" + offset;
+
+ if (dst != 0)
+ NewTimeZone += DSTZone;
+
+ DataManager::SetValue(TW_TIME_ZONE_VAR, NewTimeZone);
+ DataManager::update_tz_environment_variables();
+ return 0;
+}
+
+int GUIAction::overlay(std::string arg)
+{
+ return gui_changeOverlay(arg);
+}
+
+int GUIAction::queuezip(std::string arg)
+{
+ if (zip_queue_index >= 10) {
+ gui_print("Maximum zip queue reached!\n");
+ return 0;
+ }
+ DataManager::GetValue("tw_filename", zip_queue[zip_queue_index]);
+ if (strlen(zip_queue[zip_queue_index].c_str()) > 0) {
+ zip_queue_index++;
+ DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
+ }
+ return 0;
+}
+
+int GUIAction::cancelzip(std::string arg)
+{
+ if (zip_queue_index <= 0) {
+ gui_print("Minimum zip queue reached!\n");
+ return 0;
+ } else {
+ zip_queue_index--;
+ DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
+ }
+ return 0;
+}
+
+int GUIAction::queueclear(std::string arg)
+{
+ zip_queue_index = 0;
+ DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
+ return 0;
+}
+
+int GUIAction::sleep(std::string arg)
+{
+ operation_start("Sleep");
+ usleep(atoi(arg.c_str()));
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::appenddatetobackupname(std::string arg)
+{
+ operation_start("AppendDateToBackupName");
+ string Backup_Name;
+ DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
+ Backup_Name += TWFunc::Get_Current_Date();
+ if (Backup_Name.size() > MAX_BACKUP_NAME_LEN)
+ Backup_Name.resize(MAX_BACKUP_NAME_LEN);
+ DataManager::SetValue(TW_BACKUP_NAME, Backup_Name);
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::generatebackupname(std::string arg)
+{
+ operation_start("GenerateBackupName");
+ TWFunc::Auto_Generate_Backup_Name();
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::checkpartitionlist(std::string arg)
+{
+ string Wipe_List, wipe_path;
+ int count = 0;
+
+ DataManager::GetValue("tw_wipe_list", Wipe_List);
+ LOGINFO("checkpartitionlist list '%s'\n", Wipe_List.c_str());
+ if (!Wipe_List.empty()) {
+ size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
+ while (end_pos != string::npos && start_pos < Wipe_List.size()) {
+ wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
+ LOGINFO("checkpartitionlist wipe_path '%s'\n", wipe_path.c_str());
+ if (wipe_path == "/and-sec" || wipe_path == "DALVIK" || wipe_path == "INTERNAL") {
+ // Do nothing
+ } else {
+ count++;
+ }
+ start_pos = end_pos + 1;
+ end_pos = Wipe_List.find(";", start_pos);
+ }
+ DataManager::SetValue("tw_check_partition_list", count);
+ } else {
+ DataManager::SetValue("tw_check_partition_list", 0);
+ }
+ return 0;
+}
+
+int GUIAction::getpartitiondetails(std::string arg)
+{
+ string Wipe_List, wipe_path;
+ int count = 0;
+
+ DataManager::GetValue("tw_wipe_list", Wipe_List);
+ LOGINFO("getpartitiondetails list '%s'\n", Wipe_List.c_str());
+ if (!Wipe_List.empty()) {
+ size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
+ while (end_pos != string::npos && start_pos < Wipe_List.size()) {
+ wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
+ LOGINFO("getpartitiondetails wipe_path '%s'\n", wipe_path.c_str());
+ if (wipe_path == "/and-sec" || wipe_path == "DALVIK" || wipe_path == "INTERNAL") {
+ // Do nothing
+ } else {
+ DataManager::SetValue("tw_partition_path", wipe_path);
+ break;
+ }
+ start_pos = end_pos + 1;
+ end_pos = Wipe_List.find(";", start_pos);
+ }
+ if (!wipe_path.empty()) {
+ TWPartition* Part = PartitionManager.Find_Partition_By_Path(wipe_path);
+ if (Part) {
+ unsigned long long mb = 1048576;
+
+ DataManager::SetValue("tw_partition_name", Part->Display_Name);
+ DataManager::SetValue("tw_partition_mount_point", Part->Mount_Point);
+ DataManager::SetValue("tw_partition_file_system", Part->Current_File_System);
+ DataManager::SetValue("tw_partition_size", Part->Size / mb);
+ DataManager::SetValue("tw_partition_used", Part->Used / mb);
+ DataManager::SetValue("tw_partition_free", Part->Free / mb);
+ DataManager::SetValue("tw_partition_backup_size", Part->Backup_Size / mb);
+ DataManager::SetValue("tw_partition_removable", Part->Removable);
+ DataManager::SetValue("tw_partition_is_present", Part->Is_Present);
+
+ if (Part->Can_Repair())
+ DataManager::SetValue("tw_partition_can_repair", 1);
+ else
+ DataManager::SetValue("tw_partition_can_repair", 0);
+ if (Part->Can_Resize())
+ DataManager::SetValue("tw_partition_can_resize", 1);
+ else
+ DataManager::SetValue("tw_partition_can_resize", 0);
+ if (TWFunc::Path_Exists("/sbin/mkdosfs"))
+ DataManager::SetValue("tw_partition_vfat", 1);
+ else
+ DataManager::SetValue("tw_partition_vfat", 0);
+ if (TWFunc::Path_Exists("/sbin/mkfs.exfat"))
+ DataManager::SetValue("tw_partition_exfat", 1);
+ else
+ DataManager::SetValue("tw_partition_exfat", 0);
+ if (TWFunc::Path_Exists("/sbin/mkfs.f2fs"))
+ DataManager::SetValue("tw_partition_f2fs", 1);
+ else
+ DataManager::SetValue("tw_partition_f2fs", 0);
+ if (TWFunc::Path_Exists("/sbin/mke2fs"))
+ DataManager::SetValue("tw_partition_ext", 1);
+ else
+ DataManager::SetValue("tw_partition_ext", 0);
+ return 0;
+ } else {
+ LOGERR("Unable to locate partition: '%s'\n", wipe_path.c_str());
+ }
+ }
+ }
+ DataManager::SetValue("tw_partition_name", "");
+ DataManager::SetValue("tw_partition_file_system", "");
+ return 0;
+}
+
+int GUIAction::screenshot(std::string arg)
+{
+ time_t tm;
+ char path[256];
+ int path_len;
+ uid_t uid = -1;
+ gid_t gid = -1;
+
+ struct passwd *pwd = getpwnam("media_rw");
+ if(pwd) {
+ uid = pwd->pw_uid;
+ gid = pwd->pw_gid;
+ }
+
+ const std::string storage = DataManager::GetCurrentStoragePath();
+ if(PartitionManager.Is_Mounted_By_Path(storage)) {
+ snprintf(path, sizeof(path), "%s/Pictures/Screenshots/", storage.c_str());
+ } else {
+ strcpy(path, "/tmp/");
+ }
+
+ if(!TWFunc::Create_Dir_Recursive(path, 0666, uid, gid))
+ return 0;
+
+ tm = time(NULL);
+ path_len = strlen(path);
+
+ // Screenshot_2014-01-01-18-21-38.png
+ strftime(path+path_len, sizeof(path)-path_len, "Screenshot_%Y-%m-%d-%H-%M-%S.png", localtime(&tm));
+
+ int res = gr_save_screenshot(path);
+ if(res == 0) {
+ chmod(path, 0666);
+ chown(path, uid, gid);
+
+ gui_print("Screenshot was saved to %s\n", path);
+
+ // blink to notify that the screenshow was taken
+ gr_color(255, 255, 255, 255);
+ gr_fill(0, 0, gr_fb_width(), gr_fb_height());
+ gr_flip();
+ gui_forceRender();
+ } else {
+ LOGERR("Failed to take a screenshot!\n");
+ }
+ return 0;
+}
+
+int GUIAction::setbrightness(std::string arg)
+{
+ return TWFunc::Set_Brightness(arg);
+}
+
+int GUIAction::fileexists(std::string arg)
+{
+ struct stat st;
+ string newpath = arg + "/.";
+
+ operation_start("FileExists");
+ if (stat(arg.c_str(), &st) == 0 || stat(newpath.c_str(), &st) == 0)
+ operation_end(0);
+ else
+ operation_end(1);
+ return 0;
+}
+
+void GUIAction::reinject_after_flash()
+{
+ if (DataManager::GetIntValue(TW_HAS_INJECTTWRP) == 1 && DataManager::GetIntValue(TW_INJECT_AFTER_ZIP) == 1) {
+ gui_print("Injecting TWRP into boot image...\n");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ TWPartition* Boot = PartitionManager.Find_Partition_By_Path("/boot");
+ if (Boot == NULL || Boot->Current_File_System != "emmc")
+ TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
+ else {
+ string injectcmd = "injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash bd=" + Boot->Actual_Block_Device;
+ TWFunc::Exec_Cmd(injectcmd);
+ }
+ gui_print("TWRP injection complete.\n");
+ }
+ }
+}
+
+int GUIAction::flash(std::string arg)
+{
+ int i, ret_val = 0, wipe_cache = 0;
+ // We're going to jump to this page first, like a loading page
+ gui_changePage(arg);
+ for (i=0; i<zip_queue_index; i++) {
+ string zip_path = zip_queue[i];
+ size_t slashpos = zip_path.find_last_of('/');
+ string zip_filename = (slashpos == string::npos) ? zip_path : zip_path.substr(slashpos + 1);
+ operation_start("Flashing");
+ DataManager::SetValue("tw_filename", zip_path);
+ DataManager::SetValue("tw_file", zip_filename);
+ DataManager::SetValue(TW_ZIP_INDEX, (i + 1));
+
+ TWFunc::SetPerformanceMode(true);
+ ret_val = flash_zip(zip_path, &wipe_cache);
+ TWFunc::SetPerformanceMode(false);
+ if (ret_val != 0) {
+ gui_print("Error flashing zip '%s'\n", zip_path.c_str());
+ ret_val = 1;
+ break;
+ }
+ }
+ zip_queue_index = 0;
+
+ if (wipe_cache) {
+ gui_print("One or more zip requested a cache wipe\nWiping cache now.\n");
+ PartitionManager.Wipe_By_Path("/cache");
+ }
+
+ reinject_after_flash();
+ PartitionManager.Update_System_Details();
+ operation_end(ret_val);
+ DataManager::SetValue(TW_ZIP_QUEUE_COUNT, zip_queue_index);
+ return 0;
+}
+
+int GUIAction::wipe(std::string arg)
+{
+ operation_start("Format");
+ DataManager::SetValue("tw_partition", arg);
+
+ int ret_val = false;
+
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ if (arg == "data")
+ ret_val = PartitionManager.Factory_Reset();
+ else if (arg == "battery")
+ ret_val = PartitionManager.Wipe_Battery_Stats();
+ else if (arg == "rotate")
+ ret_val = PartitionManager.Wipe_Rotate_Data();
+ else if (arg == "dalvik")
+ ret_val = PartitionManager.Wipe_Dalvik_Cache();
+ else if (arg == "DATAMEDIA") {
+ ret_val = PartitionManager.Format_Data();
+ } else if (arg == "INTERNAL") {
+ int has_datamedia, dual_storage;
+
+ DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
+ if (has_datamedia) {
+ ret_val = PartitionManager.Wipe_Media_From_Data();
+ } else {
+ ret_val = PartitionManager.Wipe_By_Path(DataManager::GetSettingsStoragePath());
+ }
+ } else if (arg == "EXTERNAL") {
+ string External_Path;
+
+ DataManager::GetValue(TW_EXTERNAL_PATH, External_Path);
+ ret_val = PartitionManager.Wipe_By_Path(External_Path);
+ } else if (arg == "ANDROIDSECURE") {
+ ret_val = PartitionManager.Wipe_Android_Secure();
+ } else if (arg == "LIST") {
+ string Wipe_List, wipe_path;
+ bool skip = false;
+ ret_val = true;
+ TWPartition* wipe_part = NULL;
+
+ DataManager::GetValue("tw_wipe_list", Wipe_List);
+ LOGINFO("wipe list '%s'\n", Wipe_List.c_str());
+ if (!Wipe_List.empty()) {
+ size_t start_pos = 0, end_pos = Wipe_List.find(";", start_pos);
+ while (end_pos != string::npos && start_pos < Wipe_List.size()) {
+ wipe_path = Wipe_List.substr(start_pos, end_pos - start_pos);
+ LOGINFO("wipe_path '%s'\n", wipe_path.c_str());
+ if (wipe_path == "/and-sec") {
+ if (!PartitionManager.Wipe_Android_Secure()) {
+ LOGERR("Unable to wipe android secure\n");
+ ret_val = false;
+ break;
+ } else {
+ skip = true;
+ }
+ } else if (wipe_path == "DALVIK") {
+ if (!PartitionManager.Wipe_Dalvik_Cache()) {
+ LOGERR("Failed to wipe dalvik\n");
+ ret_val = false;
+ break;
+ } else {
+ skip = true;
+ }
+ } else if (wipe_path == "INTERNAL") {
+ if (!PartitionManager.Wipe_Media_From_Data()) {
+ ret_val = false;
+ break;
+ } else {
+ skip = true;
+ }
+ }
+ if (!skip) {
+ if (!PartitionManager.Wipe_By_Path(wipe_path)) {
+ LOGERR("Unable to wipe '%s'\n", wipe_path.c_str());
+ ret_val = false;
+ break;
+ } else if (wipe_path == DataManager::GetSettingsStoragePath()) {
+ arg = wipe_path;
+ }
+ } else {
+ skip = false;
+ }
+ start_pos = end_pos + 1;
+ end_pos = Wipe_List.find(";", start_pos);
+ }
+ }
+ } else
+ ret_val = PartitionManager.Wipe_By_Path(arg);
+#ifndef TW_OEM_BUILD
+ if (arg == DataManager::GetSettingsStoragePath()) {
+ // If we wiped the settings storage path, recreate the TWRP folder and dump the settings
+ string Storage_Path = DataManager::GetSettingsStoragePath();
+
+ if (PartitionManager.Mount_By_Path(Storage_Path, true)) {
+ LOGINFO("Making TWRP folder and saving settings.\n");
+ Storage_Path += "/TWRP";
+ mkdir(Storage_Path.c_str(), 0777);
+ DataManager::Flush();
+ } else {
+ LOGERR("Unable to recreate TWRP folder and save settings.\n");
+ }
+ }
+#endif
+ }
+ PartitionManager.Update_System_Details();
+ if (ret_val)
+ ret_val = 0; // 0 is success
+ else
+ ret_val = 1; // 1 is failure
+ operation_end(ret_val);
+ return 0;
+}
+
+int GUIAction::refreshsizes(std::string arg)
+{
+ operation_start("Refreshing Sizes");
+ if (simulate) {
+ simulate_progress_bar();
+ } else
+ PartitionManager.Update_System_Details();
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::nandroid(std::string arg)
+{
+ if (simulate) {
+ PartitionManager.stop_backup.set_value(0);
+ DataManager::SetValue("tw_partition", "Simulation");
+ simulate_progress_bar();
+ operation_end(0);
+ } else {
+ operation_start("Nandroid");
+ int ret = 0;
+
+ if (arg == "backup") {
+ string Backup_Name;
+ DataManager::GetValue(TW_BACKUP_NAME, Backup_Name);
+ if (Backup_Name == "(Auto Generate)" || Backup_Name == "(Current Date)" || Backup_Name == "0" || Backup_Name == "(" || PartitionManager.Check_Backup_Name(true) == 0) {
+ ret = PartitionManager.Run_Backup();
+ }
+ else {
+ operation_end(1);
+ return -1;
+ }
+ DataManager::SetValue(TW_BACKUP_NAME, "(Auto Generate)");
+ } else if (arg == "restore") {
+ string Restore_Name;
+ DataManager::GetValue("tw_restore", Restore_Name);
+ ret = PartitionManager.Run_Restore(Restore_Name);
+ } else {
+ operation_end(1);
+ return -1;
+ }
+ DataManager::SetValue("tw_encrypt_backup", 0);
+ if (!PartitionManager.stop_backup.get_value()) {
+ if (ret == false)
+ ret = 1; // 1 for failure
+ else
+ ret = 0; // 0 for success
+ DataManager::SetValue("tw_cancel_backup", 0);
+ }
+ else {
+ DataManager::SetValue("tw_cancel_backup", 1);
+ gui_print("Backup Canceled.\n");
+ ret = 0;
+ }
+ operation_end(ret);
+ return ret;
+ }
+ return 0;
+}
+
+int GUIAction::cancelbackup(std::string arg) {
+ if (simulate) {
+ PartitionManager.stop_backup.set_value(1);
+ }
+ else {
+ int op_status = PartitionManager.Cancel_Backup();
+ if (op_status != 0)
+ op_status = 1; // failure
+ }
+
+ return 0;
+}
+
+int GUIAction::fixpermissions(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Fix Permissions");
+ LOGINFO("fix permissions started!\n");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ op_status = PartitionManager.Fix_Permissions();
+ if (op_status != 0)
+ op_status = 1; // failure
+ }
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::dd(std::string arg)
+{
+ operation_start("imaging");
+
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ string cmd = "dd " + arg;
+ TWFunc::Exec_Cmd(cmd);
+ }
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::partitionsd(std::string arg)
+{
+ operation_start("Partition SD Card");
+ int ret_val = 0;
+
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ int allow_partition;
+ DataManager::GetValue(TW_ALLOW_PARTITION_SDCARD, allow_partition);
+ if (allow_partition == 0) {
+ gui_print("This device does not have a real SD Card!\nAborting!\n");
+ } else {
+ if (!PartitionManager.Partition_SDCard())
+ ret_val = 1; // failed
+ }
+ }
+ operation_end(ret_val);
+ return 0;
+
+}
+
+int GUIAction::installhtcdumlock(std::string arg)
+{
+ operation_start("Install HTC Dumlock");
+ if (simulate) {
+ simulate_progress_bar();
+ } else
+ TWFunc::install_htc_dumlock();
+
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::htcdumlockrestoreboot(std::string arg)
+{
+ operation_start("HTC Dumlock Restore Boot");
+ if (simulate) {
+ simulate_progress_bar();
+ } else
+ TWFunc::htc_dumlock_restore_original_boot();
+
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::htcdumlockreflashrecovery(std::string arg)
+{
+ operation_start("HTC Dumlock Reflash Recovery");
+ if (simulate) {
+ simulate_progress_bar();
+ } else
+ TWFunc::htc_dumlock_reflash_recovery_to_boot();
+
+ operation_end(0);
+ return 0;
+}
+
+int GUIAction::cmd(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Command");
+ LOGINFO("Running command: '%s'\n", arg.c_str());
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ op_status = TWFunc::Exec_Cmd(arg);
+ if (op_status != 0)
+ op_status = 1;
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::terminalcommand(std::string arg)
+{
+ int op_status = 0;
+ string cmdpath, command;
+
+ DataManager::GetValue("tw_terminal_location", cmdpath);
+ operation_start("CommandOutput");
+ gui_print("%s # %s\n", cmdpath.c_str(), arg.c_str());
+ if (simulate) {
+ simulate_progress_bar();
+ operation_end(op_status);
+ } else if (arg == "exit") {
+ LOGINFO("Exiting terminal\n");
+ operation_end(op_status);
+ page("main");
+ } else {
+ command = "cd \"" + cmdpath + "\" && " + arg + " 2>&1";;
+ LOGINFO("Actual command is: '%s'\n", command.c_str());
+ DataManager::SetValue("tw_terminal_state", 1);
+ DataManager::SetValue("tw_background_thread_running", 1);
+ FILE* fp;
+ char line[512];
+
+ fp = popen(command.c_str(), "r");
+ if (fp == NULL) {
+ LOGERR("Error opening command to run.\n");
+ } else {
+ int fd = fileno(fp), has_data = 0, check = 0, keep_going = -1, bytes_read = 0;
+ struct timeval timeout;
+ fd_set fdset;
+
+ while(keep_going)
+ {
+ FD_ZERO(&fdset);
+ FD_SET(fd, &fdset);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 400000;
+ has_data = select(fd+1, &fdset, NULL, NULL, &timeout);
+ if (has_data == 0) {
+ // Timeout reached
+ DataManager::GetValue("tw_terminal_state", check);
+ if (check == 0) {
+ keep_going = 0;
+ }
+ } else if (has_data < 0) {
+ // End of execution
+ keep_going = 0;
+ } else {
+ // Try to read output
+ if(fgets(line, sizeof(line), fp) != NULL)
+ gui_print("%s", line); // Display output
+ else
+ keep_going = 0; // Done executing
+ }
+ }
+ fclose(fp);
+ }
+ DataManager::SetValue("tw_operation_status", 0);
+ DataManager::SetValue("tw_operation_state", 1);
+ DataManager::SetValue("tw_terminal_state", 0);
+ DataManager::SetValue("tw_background_thread_running", 0);
+ DataManager::SetValue(TW_ACTION_BUSY, 0);
+ }
+ return 0;
+}
+
+int GUIAction::killterminal(std::string arg)
+{
+ int op_status = 0;
+
+ LOGINFO("Sending kill command...\n");
+ operation_start("KillCommand");
+ DataManager::SetValue("tw_operation_status", 0);
+ DataManager::SetValue("tw_operation_state", 1);
+ DataManager::SetValue("tw_terminal_state", 0);
+ DataManager::SetValue("tw_background_thread_running", 0);
+ DataManager::SetValue(TW_ACTION_BUSY, 0);
+ return 0;
+}
+
+int GUIAction::reinjecttwrp(std::string arg)
+{
+ int op_status = 0;
+ operation_start("ReinjectTWRP");
+ gui_print("Injecting TWRP into boot image...\n");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ TWFunc::Exec_Cmd("injecttwrp --dump /tmp/backup_recovery_ramdisk.img /tmp/injected_boot.img --flash");
+ gui_print("TWRP injection complete.\n");
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::checkbackupname(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("CheckBackupName");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ op_status = PartitionManager.Check_Backup_Name(true);
+ if (op_status != 0)
+ op_status = 1;
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::decrypt(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Decrypt");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ string Password;
+ DataManager::GetValue("tw_crypto_password", Password);
+ op_status = PartitionManager.Decrypt_Device(Password);
+ if (op_status != 0)
+ op_status = 1;
+ else {
+
+ DataManager::SetValue(TW_IS_ENCRYPTED, 0);
+
+ int has_datamedia;
+
+ // Check for a custom theme and load it if exists
+ DataManager::GetValue(TW_HAS_DATA_MEDIA, has_datamedia);
+ if (has_datamedia != 0) {
+ if (tw_get_default_metadata(DataManager::GetSettingsStoragePath().c_str()) != 0) {
+ LOGINFO("Failed to get default contexts and file mode for storage files.\n");
+ } else {
+ LOGINFO("Got default contexts and file mode for storage files.\n");
+ }
+ }
+ }
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::adbsideload(std::string arg)
+{
+ operation_start("Sideload");
+ if (simulate) {
+ simulate_progress_bar();
+ operation_end(0);
+ } else {
+ gui_print("Starting ADB sideload feature...\n");
+ bool mtp_was_enabled = TWFunc::Toggle_MTP(false);
+
+ // wait for the adb connection
+ int ret = apply_from_adb("/", &sideload_child_pid);
+ DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui now that the zip install is going to start
+
+ if (ret != 0) {
+ if (ret == -2)
+ gui_print("You need adb 1.0.32 or newer to sideload to this device.\n");
+ ret = 1; // failure
+ } else {
+ int wipe_cache = 0;
+ int wipe_dalvik = 0;
+ DataManager::GetValue("tw_wipe_dalvik", wipe_dalvik);
+
+ if (TWinstall_zip(FUSE_SIDELOAD_HOST_PATHNAME, &wipe_cache) == 0) {
+ if (wipe_cache || DataManager::GetIntValue("tw_wipe_cache"))
+ PartitionManager.Wipe_By_Path("/cache");
+ if (wipe_dalvik)
+ PartitionManager.Wipe_Dalvik_Cache();
+ } else {
+ ret = 1; // failure
+ }
+ }
+ if (sideload_child_pid) {
+ LOGINFO("Signaling child sideload process to exit.\n");
+ struct stat st;
+ // Calling stat() on this magic filename signals the minadbd
+ // subprocess to shut down.
+ stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
+ int status;
+ LOGINFO("Waiting for child sideload process to exit.\n");
+ waitpid(sideload_child_pid, &status, 0);
+ }
+ property_set("ctl.start", "adbd");
+ TWFunc::Toggle_MTP(mtp_was_enabled);
+ reinject_after_flash();
+ operation_end(ret);
+ }
+ return 0;
+}
+
+int GUIAction::adbsideloadcancel(std::string arg)
+{
+ struct stat st;
+ DataManager::SetValue("tw_has_cancel", 0); // Remove cancel button from gui
+ gui_print("Cancelling ADB sideload...\n");
+ LOGINFO("Signaling child sideload process to exit.\n");
+ // Calling stat() on this magic filename signals the minadbd
+ // subprocess to shut down.
+ stat(FUSE_SIDELOAD_HOST_EXIT_PATHNAME, &st);
+ if (!sideload_child_pid) {
+ LOGERR("Unable to get child ID\n");
+ return 0;
+ }
+ ::sleep(1);
+ LOGINFO("Killing child sideload process.\n");
+ kill(sideload_child_pid, SIGTERM);
+ int status;
+ LOGINFO("Waiting for child sideload process to exit.\n");
+ waitpid(sideload_child_pid, &status, 0);
+ sideload_child_pid = 0;
+ DataManager::SetValue("tw_page_done", "1"); // For OpenRecoveryScript support
+ return 0;
+}
+
+int GUIAction::openrecoveryscript(std::string arg)
+{
+ int op_status = 1;
+
+ operation_start("OpenRecoveryScript");
+ if (simulate) {
+ simulate_progress_bar();
+ operation_end(0);
+ } else {
+ // Check for the SCRIPT_FILE_TMP first as these are AOSP recovery commands
+ // that we converted to ORS commands during boot in recovery.cpp.
+ // Run those first.
+ int reboot = 0;
+ if (TWFunc::Path_Exists(SCRIPT_FILE_TMP)) {
+ gui_print("Processing AOSP recovery commands...\n");
+ if (OpenRecoveryScript::run_script_file() == 0) {
+ reboot = 1;
+ op_status = 0;
+ }
+ }
+ // Check for the ORS file in /cache and attempt to run those commands.
+ if (OpenRecoveryScript::check_for_script_file()) {
+ gui_print("Processing OpenRecoveryScript file...\n");
+ if (OpenRecoveryScript::run_script_file() == 0) {
+ reboot = 1;
+ op_status = 0;
+ }
+ }
+ if (reboot) {
+ // Disable stock recovery reflashing
+ TWFunc::Disable_Stock_Recovery_Replace();
+ usleep(2000000); // Sleep for 2 seconds before rebooting
+ TWFunc::tw_reboot(rb_system);
+ usleep(5000000); // Sleep for 5 seconds to allow reboot to occur
+ } else {
+ DataManager::SetValue("tw_page_done", 1);
+ }
+ operation_end(op_status);
+ }
+ return 0;
+}
+
+int GUIAction::installsu(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Install SuperSU");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ if (!TWFunc::Install_SuperSU())
+ op_status = 1;
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::fixsu(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Fixing Superuser Permissions");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ LOGERR("Fixing su permissions was deprecated from TWRP.\n");
+ LOGERR("4.3+ ROMs with SELinux will always lose su perms.\n");
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::decrypt_backup(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Try Restore Decrypt");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ string Restore_Path, Filename, Password;
+ DataManager::GetValue("tw_restore", Restore_Path);
+ Restore_Path += "/";
+ DataManager::GetValue("tw_restore_password", Password);
+ TWFunc::SetPerformanceMode(true);
+ if (TWFunc::Try_Decrypting_Backup(Restore_Path, Password))
+ op_status = 0; // success
+ else
+ op_status = 1; // fail
+ TWFunc::SetPerformanceMode(false);
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::repair(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Repair Partition");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ string part_path;
+ DataManager::GetValue("tw_partition_mount_point", part_path);
+ if (PartitionManager.Repair_By_Path(part_path, true)) {
+ op_status = 0; // success
+ } else {
+ LOGERR("Error repairing file system.\n");
+ op_status = 1; // fail
+ }
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::resize(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Resize Partition");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ string part_path;
+ DataManager::GetValue("tw_partition_mount_point", part_path);
+ if (PartitionManager.Resize_By_Path(part_path, true)) {
+ op_status = 0; // success
+ } else {
+ LOGERR("Error resizing file system.\n");
+ op_status = 1; // fail
+ }
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::changefilesystem(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Change File System");
+ if (simulate) {
+ simulate_progress_bar();
+ } else {
+ string part_path, file_system;
+ DataManager::GetValue("tw_partition_mount_point", part_path);
+ DataManager::GetValue("tw_action_new_file_system", file_system);
+ if (PartitionManager.Wipe_By_Path(part_path, file_system)) {
+ op_status = 0; // success
+ } else {
+ LOGERR("Error changing file system.\n");
+ op_status = 1; // fail
+ }
+ }
+ PartitionManager.Update_System_Details();
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::startmtp(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Start MTP");
+ if (PartitionManager.Enable_MTP())
+ op_status = 0; // success
+ else
+ op_status = 1; // fail
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::stopmtp(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Stop MTP");
+ if (PartitionManager.Disable_MTP())
+ op_status = 0; // success
+ else
+ op_status = 1; // fail
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::flashimage(std::string arg)
+{
+ int op_status = 0;
+
+ operation_start("Flash Image");
+ string path, filename, full_filename;
+ DataManager::GetValue("tw_zip_location", path);
+ DataManager::GetValue("tw_file", filename);
+ full_filename = path + "/" + filename;
+ if (PartitionManager.Flash_Image(full_filename))
+ op_status = 0; // success
+ else
+ op_status = 1; // fail
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::getKeyByName(std::string key)
+{
+ if (key == "home") return KEY_HOME;
+ else if (key == "menu") return KEY_MENU;
+ else if (key == "back") return KEY_BACK;
+ else if (key == "search") return KEY_SEARCH;
+ else if (key == "voldown") return KEY_VOLUMEDOWN;
+ else if (key == "volup") return KEY_VOLUMEUP;
+ else if (key == "power") {
+ int ret_val;
+ DataManager::GetValue(TW_POWER_BUTTON, ret_val);
+ if (!ret_val)
+ return KEY_POWER;
+ else
+ return ret_val;
+ }
+
+ return atol(key.c_str());
+}
+
+int GUIAction::checkpartitionlifetimewrites(std::string arg)
+{
+ int op_status = 0;
+ TWPartition* sys = PartitionManager.Find_Partition_By_Path(arg);
+
+ operation_start("Check Partition Lifetime Writes");
+ if (sys) {
+ if (sys->Check_Lifetime_Writes() != 0)
+ DataManager::SetValue("tw_lifetime_writes", 1);
+ else
+ DataManager::SetValue("tw_lifetime_writes", 0);
+ op_status = 0; // success
+ } else {
+ DataManager::SetValue("tw_lifetime_writes", 1);
+ op_status = 1; // fail
+ }
+
+ operation_end(op_status);
+ return 0;
+}
+
+int GUIAction::mountsystemtoggle(std::string arg)
+{
+ int op_status = 0;
+ bool remount_system = PartitionManager.Is_Mounted_By_Path("/system");
+
+ operation_start("Toggle System Mount");
+ if (!PartitionManager.UnMount_By_Path("/system", true)) {
+ op_status = 1; // fail
+ } else {
+ TWPartition* Part = PartitionManager.Find_Partition_By_Path("/system");
+ if (Part) {
+ if (arg == "0") {
+ DataManager::SetValue("tw_mount_system_ro", 0);
+ Part->Change_Mount_Read_Only(false);
+ } else {
+ DataManager::SetValue("tw_mount_system_ro", 1);
+ Part->Change_Mount_Read_Only(true);
+ }
+ if (remount_system) {
+ Part->Mount(true);
+ }
+ op_status = 0; // success
+ } else {
+ op_status = 1; // fail
+ }
+ }
+
+ operation_end(op_status);
+ return 0;
+}
diff --git a/gui/animation.cpp b/gui/animation.cpp
new file mode 100644
index 000000000..888b4ab08
--- /dev/null
+++ b/gui/animation.cpp
@@ -0,0 +1,129 @@
+// animation.cpp - GUIAnimation object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+
+GUIAnimation::GUIAnimation(xml_node<>* node) : GUIObject(node)
+{
+ xml_node<>* child;
+
+ mAnimation = NULL;
+ mFrame = 1;
+ mFPS = 1;
+ mLoop = -1;
+ mRender = 1;
+ mUpdateCount = 0;
+
+ if (!node) return;
+
+ mAnimation = LoadAttrAnimation(FindNode(node, "resource"), "name");
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, NULL, NULL, &mPlacement);
+
+ child = FindNode(node, "speed");
+ if (child)
+ {
+ mFPS = LoadAttrInt(child, "fps", mFPS);
+ mRender = LoadAttrInt(child, "render", mRender);
+ }
+ if (mFPS > 30) mFPS = 30;
+
+ child = FindNode(node, "loop");
+ if (child)
+ {
+ xml_attribute<>* attr = child->first_attribute("frame");
+ if (attr)
+ mLoop = atoi(attr->value()) - 1;
+ mFrame = LoadAttrInt(child, "start", mFrame);
+ }
+
+ // Fetch the render sizes
+ if (mAnimation && mAnimation->GetResource())
+ {
+ mRenderW = mAnimation->GetWidth();
+ mRenderH = mAnimation->GetHeight();
+
+ // Adjust for placement
+ if (mPlacement != TOP_LEFT && mPlacement != BOTTOM_LEFT)
+ {
+ if (mPlacement == CENTER)
+ mRenderX -= (mRenderW / 2);
+ else
+ mRenderX -= mRenderW;
+ }
+ if (mPlacement != TOP_LEFT && mPlacement != TOP_RIGHT)
+ {
+ if (mPlacement == CENTER)
+ mRenderY -= (mRenderH / 2);
+ else
+ mRenderY -= mRenderH;
+ }
+ SetPlacement(TOP_LEFT);
+ }
+}
+
+int GUIAnimation::Render(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ if (!mAnimation || !mAnimation->GetResource(mFrame)) return -1;
+
+ gr_blit(mAnimation->GetResource(mFrame), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
+ return 0;
+}
+
+int GUIAnimation::Update(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ if (!mAnimation) return -1;
+
+ // Handle the "end-of-animation" state
+ if (mLoop == -2) return 0;
+
+ // Determine if we need the next frame yet...
+ if (++mUpdateCount > 30 / mFPS)
+ {
+ mUpdateCount = 0;
+ if (++mFrame >= mAnimation->GetResourceCount())
+ {
+ if (mLoop < 0)
+ {
+ mFrame = mAnimation->GetResourceCount() - 1;
+ mLoop = -2;
+ }
+ else
+ mFrame = mLoop;
+ }
+ if (mRender == 2) return 2;
+ return (Render() == 0 ? 1 : -1);
+ }
+ return 0;
+}
+
diff --git a/gui/blanktimer.cpp b/gui/blanktimer.cpp
new file mode 100644
index 000000000..95b6c47ff
--- /dev/null
+++ b/gui/blanktimer.cpp
@@ -0,0 +1,123 @@
+/*
+ Copyright 2012 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+using namespace std;
+#include <string>
+#include <pthread.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include "pages.hpp"
+#include "blanktimer.hpp"
+#include "../data.hpp"
+extern "C" {
+#include "../minuitwrp/minui.h"
+#include "../twcommon.h"
+}
+#include "../twrp-functions.hpp"
+#include "../variables.h"
+
+blanktimer::blanktimer(void) {
+ pthread_mutex_init(&mutex, NULL);
+ setTime(0); // no timeout
+ state = kOn;
+ orig_brightness = getBrightness();
+}
+
+bool blanktimer::isScreenOff() {
+ return state >= kOff;
+}
+
+void blanktimer::setTime(int newtime) {
+ pthread_mutex_lock(&mutex);
+ sleepTimer = newtime;
+ pthread_mutex_unlock(&mutex);
+}
+
+void blanktimer::setTimer(void) {
+ clock_gettime(CLOCK_MONOTONIC, &btimer);
+}
+
+void blanktimer::checkForTimeout() {
+#ifndef TW_NO_SCREEN_TIMEOUT
+ pthread_mutex_lock(&mutex);
+ timespec curTime, diff;
+ clock_gettime(CLOCK_MONOTONIC, &curTime);
+ diff = TWFunc::timespec_diff(btimer, curTime);
+ if (sleepTimer > 2 && diff.tv_sec > (sleepTimer - 2) && state == kOn) {
+ orig_brightness = getBrightness();
+ state = kDim;
+ TWFunc::Set_Brightness("5");
+ }
+ if (sleepTimer && diff.tv_sec > sleepTimer && state < kOff) {
+ state = kOff;
+ TWFunc::Set_Brightness("0");
+ TWFunc::check_and_run_script("/sbin/postscreenblank.sh", "blank");
+ PageManager::ChangeOverlay("lock");
+ }
+#ifndef TW_NO_SCREEN_BLANK
+ if (state == kOff && gr_fb_blank(1) >= 0) {
+ state = kBlanked;
+ }
+#endif
+ pthread_mutex_unlock(&mutex);
+#endif
+}
+
+string blanktimer::getBrightness(void) {
+ string result;
+ string brightness_path;
+ DataManager::GetValue("tw_brightness_file", brightness_path);
+ if (brightness_path == "/nobrightness")
+ return brightness_path;
+ DataManager::GetValue("tw_brightness", result);
+ if (result == "") {
+ result = "255";
+ }
+ return result;
+
+}
+
+void blanktimer::resetTimerAndUnblank(void) {
+#ifndef TW_NO_SCREEN_TIMEOUT
+ pthread_mutex_lock(&mutex);
+ setTimer();
+ switch (state) {
+ case kBlanked:
+#ifndef TW_NO_SCREEN_BLANK
+ if (gr_fb_blank(0) < 0) {
+ LOGINFO("blanktimer::resetTimerAndUnblank failed to gr_fb_blank(0)\n");
+ break;
+ }
+#endif
+ // TODO: this is asymmetric with postscreenblank.sh - shouldn't it be under the next case label?
+ TWFunc::check_and_run_script("/sbin/postscreenunblank.sh", "unblank");
+ // No break here, we want to keep going
+ case kOff:
+ gui_forceRender();
+ // No break here, we want to keep going
+ case kDim:
+ if (orig_brightness != "/nobrightness")
+ TWFunc::Set_Brightness(orig_brightness);
+ state = kOn;
+ case kOn:
+ break;
+ }
+ pthread_mutex_unlock(&mutex);
+#endif
+}
diff --git a/gui/blanktimer.hpp b/gui/blanktimer.hpp
new file mode 100644
index 000000000..5e617901f
--- /dev/null
+++ b/gui/blanktimer.hpp
@@ -0,0 +1,56 @@
+/*
+ Copyright 2012 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef __BLANKTIMER_HEADER_HPP
+#define __BLANKTIMER_HEADER_HPP
+
+#include <sys/time.h>
+
+using namespace std;
+
+class blanktimer
+{
+public:
+ blanktimer();
+
+ // set timeout in seconds
+ void setTime(int newtime);
+
+ // call this in regular intervals
+ void checkForTimeout();
+
+ // call this when an input event is received or when an operation is finished
+ void resetTimerAndUnblank();
+
+ bool isScreenOff();
+
+private:
+ void setTimer(void);
+ string getBrightness(void);
+
+ pthread_mutex_t mutex;
+ enum State { kOn = 0, kDim = 1, kOff = 2, kBlanked = 3 };
+ State state;
+ timespec btimer;
+ long sleepTimer;
+ string orig_brightness;
+};
+
+extern blanktimer blankTimer;
+
+#endif // __BLANKTIMER_HEADER_HPP
diff --git a/gui/button.cpp b/gui/button.cpp
new file mode 100644
index 000000000..18b5560c4
--- /dev/null
+++ b/gui/button.cpp
@@ -0,0 +1,261 @@
+/*
+ Copyright 2012 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "../data.hpp"
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUIButton::GUIButton(xml_node<>* node)
+ : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ mButtonImg = NULL;
+ mButtonIcon = NULL;
+ mButtonLabel = NULL;
+ mAction = NULL;
+ mRendered = false;
+ hasHighlightColor = false;
+ renderHighlight = false;
+ hasFill = false;
+
+ if (!node) return;
+
+ // These can be loaded directly from the node
+ mButtonLabel = new GUIText(node);
+ mAction = new GUIAction(node);
+
+ mButtonImg = new GUIImage(node);
+ if (mButtonImg->Render() < 0)
+ {
+ delete mButtonImg;
+ mButtonImg = NULL;
+ }
+ if (mButtonLabel->Render() < 0)
+ {
+ delete mButtonLabel;
+ mButtonLabel = NULL;
+ }
+ // Load fill if it exists
+ mFillColor = LoadAttrColor(FindNode(node, "fill"), "color", &hasFill);
+ if (!hasFill && mButtonImg == NULL) {
+ LOGERR("No image resource or fill specified for button.\n");
+ }
+
+ // The icon is a special case
+ mButtonIcon = LoadAttrImage(FindNode(node, "icon"), "resource");
+
+ mHighlightColor = LoadAttrColor(FindNode(node, "highlight"), "color", &hasHighlightColor);
+
+ int x, y, w, h;
+ TextPlacement = TOP_LEFT;
+ if (mButtonImg) {
+ mButtonImg->GetRenderPos(x, y, w, h);
+ } else if (hasFill) {
+ LoadPlacement(FindNode(node, "placement"), &x, &y, &w, &h, &TextPlacement);
+ }
+ SetRenderPos(x, y, w, h);
+}
+
+GUIButton::~GUIButton()
+{
+ delete mButtonImg;
+ delete mButtonLabel;
+ delete mAction;
+}
+
+int GUIButton::Render(void)
+{
+ if (!isConditionTrue())
+ {
+ mRendered = false;
+ return 0;
+ }
+
+ int ret = 0;
+
+ if (mButtonImg) ret = mButtonImg->Render();
+ if (ret < 0) return ret;
+ if (hasFill) {
+ gr_color(mFillColor.red, mFillColor.green, mFillColor.blue, mFillColor.alpha);
+ gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
+ }
+ if (mButtonIcon && mButtonIcon->GetResource())
+ gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY);
+ if (mButtonLabel) {
+ int w, h;
+ mButtonLabel->GetCurrentBounds(w, h);
+ if (w != mTextW) {
+ mTextW = w;
+ if (TextPlacement == CENTER_X_ONLY) {
+ mTextX = ((mRenderW - mRenderX) / 2);
+ } else if (mTextW > mRenderW) { // As a special case, we'll allow large text which automatically moves it to the right.
+ mTextX = mRenderW + mRenderX + 5;
+ mRenderW += mTextW + 5;
+ } else {
+ mTextX = mRenderX + ((mRenderW - mTextW) / 2);
+ }
+ mButtonLabel->SetRenderPos(mTextX, mTextY);
+ }
+ ret = mButtonLabel->Render();
+ if (ret < 0) return ret;
+ }
+ if (renderHighlight && hasHighlightColor) {
+ gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
+ gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
+ }
+ mRendered = true;
+ return ret;
+}
+
+int GUIButton::Update(void)
+{
+ if (!isConditionTrue()) return (mRendered ? 2 : 0);
+ if (!mRendered) return 2;
+
+ int ret = 0, ret2 = 0;
+
+ if (mButtonImg) ret = mButtonImg->Update();
+ if (ret < 0) return ret;
+
+ if (ret == 0)
+ {
+ if (mButtonLabel) {
+ ret2 = mButtonLabel->Update();
+ if (ret2 < 0) return ret2;
+ if (ret2 > ret) ret = ret2;
+ }
+ }
+ else if (ret == 1)
+ {
+ // The button re-rendered, so everyone else is a render
+ if (mButtonIcon && mButtonIcon->GetResource())
+ gr_blit(mButtonIcon->GetResource(), 0, 0, mIconW, mIconH, mIconX, mIconY);
+ if (mButtonLabel) ret = mButtonLabel->Render();
+ if (ret < 0) return ret;
+ ret = 1;
+ }
+ else
+ {
+ // Aparently, the button needs a background update
+ ret = 2;
+ }
+ return ret;
+}
+
+int GUIButton::SetRenderPos(int x, int y, int w, int h)
+{
+ mRenderX = x;
+ mRenderY = y;
+ if (w || h)
+ {
+ mRenderW = w;
+ mRenderH = h;
+ }
+
+ mIconW = mButtonIcon->GetWidth();
+ mIconH = mButtonIcon->GetHeight();
+
+ mTextH = 0;
+ mTextW = 0;
+ mIconX = mRenderX + ((mRenderW - mIconW) / 2);
+ if (mButtonLabel) mButtonLabel->GetCurrentBounds(mTextW, mTextH);
+ if (mTextW)
+ {
+ if (TextPlacement == CENTER_X_ONLY) {
+ mTextX = ((mRenderW - mRenderX) / 2);
+ } else if (mTextW > mRenderW) { // As a special case, we'll allow large text which automatically moves it to the right.
+ mTextX = mRenderW + mRenderX + 5;
+ mRenderW += mTextW + 5;
+ } else {
+ mTextX = mRenderX + ((mRenderW - mTextW) / 2);
+ }
+ }
+
+ if (mIconH == 0 || mTextH == 0 || mIconH + mTextH > mRenderH)
+ {
+ mIconY = mRenderY + (mRenderH / 2) - (mIconH / 2);
+ mTextY = mRenderY + (mRenderH / 2) - (mTextH / 2);
+ }
+ else
+ {
+ int divisor = mRenderH - (mIconH + mTextH);
+ mIconY = mRenderY + (divisor / 3);
+ mTextY = mRenderY + (divisor * 2 / 3) + mIconH;
+ }
+
+ if (mButtonLabel) mButtonLabel->SetRenderPos(mTextX, mTextY);
+ if (mAction) mAction->SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+ SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+ return 0;
+}
+
+int GUIButton::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ static int last_state = 0;
+
+ if (!isConditionTrue()) return -1;
+ if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH || state == TOUCH_RELEASE) {
+ if (last_state == 1) {
+ last_state = 0;
+ if (mButtonLabel != NULL)
+ mButtonLabel->isHighlighted = false;
+ if (mButtonImg != NULL)
+ mButtonImg->isHighlighted = false;
+ renderHighlight = false;
+ mRendered = false;
+ }
+ } else {
+ if (last_state == 0) {
+ last_state = 1;
+ DataManager::Vibrate("tw_button_vibrate");
+ if (mButtonLabel != NULL)
+ mButtonLabel->isHighlighted = true;
+ if (mButtonImg != NULL)
+ mButtonImg->isHighlighted = true;
+ renderHighlight = true;
+ mRendered = false;
+ }
+ }
+ if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH)
+ return 0;
+ return (mAction ? mAction->NotifyTouch(state, x, y) : 1);
+}
diff --git a/gui/checkbox.cpp b/gui/checkbox.cpp
new file mode 100644
index 000000000..46a770861
--- /dev/null
+++ b/gui/checkbox.cpp
@@ -0,0 +1,165 @@
+// checkbox.cpp - GUICheckbox object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUICheckbox::GUICheckbox(xml_node<>* node)
+ : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ mChecked = NULL;
+ mUnchecked = NULL;
+ mLabel = NULL;
+ mRendered = false;
+
+ mLastState = 0;
+
+ if (!node)
+ return;
+
+ // The label can be loaded directly
+ mLabel = new GUIText(node);
+
+ // Read the check states
+ child = FindNode(node, "image");
+ if (child)
+ {
+ mChecked = LoadAttrImage(child, "checked");
+ mUnchecked = LoadAttrImage(child, "unchecked");
+ }
+
+ // Get the variable data
+ child = FindNode(node, "data");
+ if (child)
+ {
+ attr = child->first_attribute("variable");
+ if (attr)
+ mVarName = attr->value();
+ attr = child->first_attribute("default");
+ if (attr)
+ DataManager::SetValue(mVarName, attr->value());
+ }
+
+ mCheckW = mChecked->GetWidth();
+ mCheckH = mChecked->GetHeight();
+ if (mCheckW == 0)
+ {
+ mCheckW = mUnchecked->GetWidth();
+ mCheckH = mUnchecked->GetHeight();
+ }
+
+ int x, y, w, h;
+ mLabel->GetRenderPos(x, y, w, h);
+ SetRenderPos(x, y, 0, 0);
+}
+
+GUICheckbox::~GUICheckbox()
+{
+}
+
+int GUICheckbox::Render(void)
+{
+ if (!isConditionTrue())
+ {
+ mRendered = false;
+ return 0;
+ }
+
+ int ret = 0;
+ int lastState = 0;
+ DataManager::GetValue(mVarName, lastState);
+
+ if (lastState)
+ {
+ if (mChecked && mChecked->GetResource())
+ gr_blit(mChecked->GetResource(), 0, 0, mCheckW, mCheckH, mRenderX, mRenderY);
+ }
+ else
+ {
+ if (mUnchecked && mUnchecked->GetResource())
+ gr_blit(mUnchecked->GetResource(), 0, 0, mCheckW, mCheckH, mRenderX, mRenderY);
+ }
+ if (mLabel)
+ ret = mLabel->Render();
+ mLastState = lastState;
+ mRendered = true;
+ return ret;
+}
+
+int GUICheckbox::Update(void)
+{
+ if (!isConditionTrue()) return (mRendered ? 2 : 0);
+ if (!mRendered) return 2;
+
+ int lastState = 0;
+ DataManager::GetValue(mVarName, lastState);
+
+ if (lastState != mLastState)
+ return 2;
+ return 0;
+}
+
+int GUICheckbox::SetRenderPos(int x, int y, int w, int h)
+{
+ mRenderX = x;
+ mRenderY = y;
+
+ if (w || h)
+ return -1;
+
+ int textW, textH;
+ mLabel->GetCurrentBounds(textW, textH);
+
+ w = textW + mCheckW + 5;
+ mRenderW = w;
+ mRenderH = mCheckH;
+
+ mTextX = mRenderX + mCheckW + 5;
+ mTextY = mRenderY + ((mCheckH / 2) - (textH / 2));
+
+ mLabel->SetRenderPos(mTextX, mTextY, 0, 0);
+ SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+ return 0;
+}
+
+int GUICheckbox::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if (!isConditionTrue())
+ return -1;
+
+ if (state == TOUCH_RELEASE)
+ {
+ int lastState;
+ DataManager::GetValue(mVarName, lastState);
+ lastState = (lastState == 0) ? 1 : 0;
+ DataManager::SetValue(mVarName, lastState);
+
+ DataManager::Vibrate("tw_button_vibrate");
+ }
+ return 0;
+}
+
diff --git a/gui/console.cpp b/gui/console.cpp
new file mode 100644
index 000000000..1544d77a1
--- /dev/null
+++ b/gui/console.cpp
@@ -0,0 +1,328 @@
+// console.cpp - GUIConsole object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+
+static std::vector<std::string> gConsole;
+static std::vector<std::string> gConsoleColor;
+static FILE* ors_file;
+
+extern "C" void __gui_print(const char *color, char *buf)
+{
+ char *start, *next;
+
+ if (buf[0] == '\n' && strlen(buf) < 2) {
+ // This prevents the double lines bug seen in the console during zip installs
+ return;
+ }
+
+ for (start = next = buf; *next != '\0';)
+ {
+ if (*next == '\n')
+ {
+ *next = '\0';
+ gConsole.push_back(start);
+ gConsoleColor.push_back(color);
+
+ start = ++next;
+ }
+ else
+ ++next;
+ }
+
+ // The text after last \n (or whole string if there is no \n)
+ if(*start) {
+ gConsole.push_back(start);
+ gConsoleColor.push_back(color);
+ }
+ if (ors_file) {
+ fprintf(ors_file, "%s\n", buf);
+ fflush(ors_file);
+ }
+}
+
+extern "C" void gui_print(const char *fmt, ...)
+{
+ char buf[512]; // We're going to limit a single request to 512 bytes
+
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(buf, 512, fmt, ap);
+ va_end(ap);
+
+ fputs(buf, stdout);
+
+ __gui_print("normal", buf);
+ return;
+}
+
+extern "C" void gui_print_color(const char *color, const char *fmt, ...)
+{
+ char buf[512]; // We're going to limit a single request to 512 bytes
+
+ va_list ap;
+ va_start(ap, fmt);
+ vsnprintf(buf, 512, fmt, ap);
+ va_end(ap);
+
+ fputs(buf, stdout);
+
+ __gui_print(color, buf);
+ return;
+}
+
+extern "C" void gui_set_FILE(FILE* f)
+{
+ ors_file = f;
+}
+
+GUIConsole::GUIConsole(xml_node<>* node) : GUIScrollList(node)
+{
+ xml_node<>* child;
+
+ mLastCount = 0;
+ scrollToEnd = true;
+ mSlideoutX = mSlideoutY = mSlideoutW = mSlideoutH = 0;
+ mSlideout = 0;
+ mSlideoutState = visible;
+
+ allowSelection = false; // console doesn't support list item selections
+
+ if (!node)
+ {
+ mRenderX = 0; mRenderY = 0; mRenderW = gr_fb_width(); mRenderH = gr_fb_height();
+ }
+ else
+ {
+ child = FindNode(node, "color");
+ if (child)
+ {
+ mFontColor = LoadAttrColor(child, "foreground", mFontColor);
+ mBackgroundColor = LoadAttrColor(child, "background", mBackgroundColor);
+ //mScrollColor = LoadAttrColor(child, "scroll", mScrollColor);
+ }
+
+ child = FindNode(node, "slideout");
+ if (child)
+ {
+ mSlideout = 1;
+ mSlideoutState = hidden;
+ LoadPlacement(child, &mSlideoutX, &mSlideoutY, &mSlideoutW, &mSlideoutH, &mPlacement);
+
+ mSlideoutImage = LoadAttrImage(child, "resource");
+
+ if (mSlideoutImage && mSlideoutImage->GetResource())
+ {
+ mSlideoutW = mSlideoutImage->GetWidth();
+ mSlideoutH = mSlideoutImage->GetHeight();
+ if (mPlacement == CENTER || mPlacement == CENTER_X_ONLY) {
+ mSlideoutX = mSlideoutX - (mSlideoutW / 2);
+ if (mPlacement == CENTER) {
+ mSlideoutY = mSlideoutY - (mSlideoutH / 2);
+ }
+ }
+ }
+ }
+ }
+}
+
+int GUIConsole::RenderSlideout(void)
+{
+ if (!mSlideoutImage || !mSlideoutImage->GetResource())
+ return -1;
+
+ gr_blit(mSlideoutImage->GetResource(), 0, 0, mSlideoutW, mSlideoutH, mSlideoutX, mSlideoutY);
+ return 0;
+}
+
+bool GUIConsole::AddLines()
+{
+ if (mLastCount == gConsole.size())
+ return false; // nothing to add
+
+ size_t prevCount = mLastCount;
+ mLastCount = gConsole.size();
+
+ // Due to word wrap, figure out what / how the newly added text needs to be added to the render vector that is word wrapped
+ // Note, that multiple consoles on different GUI pages may be different widths or use different fonts, so the word wrapping
+ // may different in different console windows
+ for (size_t i = prevCount; i < mLastCount; i++) {
+ string curr_line = gConsole[i];
+ string curr_color = gConsoleColor[i];
+ for(;;) {
+ size_t line_char_width = gr_maxExW(curr_line.c_str(), mFont->GetResource(), mRenderW);
+ if (line_char_width < curr_line.size()) {
+ rConsole.push_back(curr_line.substr(0, line_char_width));
+ rConsoleColor.push_back(curr_color);
+ curr_line = curr_line.substr(line_char_width);
+ } else {
+ rConsole.push_back(curr_line);
+ rConsoleColor.push_back(curr_color);
+ break;
+ }
+ }
+ }
+ return true;
+}
+
+int GUIConsole::RenderConsole(void)
+{
+ AddLines();
+ GUIScrollList::Render();
+
+ // if last line is fully visible, keep tracking the last line when new lines are added
+ int bottom_offset = GetDisplayRemainder() - actualItemHeight;
+ bool isAtBottom = firstDisplayedItem == GetItemCount() - GetDisplayItemCount() - (bottom_offset != 0) && y_offset == bottom_offset;
+ if (isAtBottom)
+ scrollToEnd = true;
+#if 0
+ // debug - show if we are tracking the last line
+ if (scrollToEnd) {
+ gr_color(0,255,0,255);
+ gr_fill(mRenderX+mRenderW-5, mRenderY+mRenderH-5, 5, 5);
+ } else {
+ gr_color(255,0,0,255);
+ gr_fill(mRenderX+mRenderW-5, mRenderY+mRenderH-5, 5, 5);
+ }
+#endif
+ return (mSlideout ? RenderSlideout() : 0);
+}
+
+int GUIConsole::Render(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ if (mSlideout && mSlideoutState == hidden)
+ return RenderSlideout();
+
+ return RenderConsole();
+}
+
+int GUIConsole::Update(void)
+{
+ if (mSlideout && mSlideoutState != visible)
+ {
+ if (mSlideoutState == hidden)
+ return 0;
+
+ if (mSlideoutState == request_hide)
+ mSlideoutState = hidden;
+
+ if (mSlideoutState == request_show)
+ mSlideoutState = visible;
+
+ // Any time we activate the console, we reset the position
+ SetVisibleListLocation(rConsole.size() - 1);
+ mUpdate = 1;
+ scrollToEnd = true;
+ }
+
+ if (AddLines()) {
+ // someone added new text
+ // at least the scrollbar must be updated, even if the new lines are currently not visible
+ mUpdate = 1;
+ }
+
+ if (scrollToEnd) {
+ // keep the last line in view
+ SetVisibleListLocation(rConsole.size() - 1);
+ }
+
+ GUIScrollList::Update();
+
+ if (mUpdate) {
+ mUpdate = 0;
+ if (Render() == 0)
+ return 2;
+ }
+ return 0;
+}
+
+// IsInRegion - Checks if the request is handled by this object
+// Return 1 if this object handles the request, 0 if not
+int GUIConsole::IsInRegion(int x, int y)
+{
+ if (mSlideout) {
+ // Check if they tapped the slideout button
+ if (x >= mSlideoutX && x < mSlideoutX + mSlideoutW && y >= mSlideoutY && y < mSlideoutY + mSlideoutH)
+ return 1;
+
+ // If we're only rendering the slideout, bail now
+ if (mSlideoutState == hidden)
+ return 0;
+ }
+
+ return GUIScrollList::IsInRegion(x, y);
+}
+
+// NotifyTouch - Notify of a touch event
+// Return 0 on success, >0 to ignore remainder of touch, and <0 on error
+int GUIConsole::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if(!isConditionTrue())
+ return -1;
+
+ if (mSlideout && x >= mSlideoutX && x < mSlideoutX + mSlideoutW && y >= mSlideoutY && y < mSlideoutY + mSlideoutH) {
+ if (state == TOUCH_START) {
+ if (mSlideoutState == hidden)
+ mSlideoutState = request_show;
+ else if (mSlideoutState == visible)
+ mSlideoutState = request_hide;
+ }
+ return 1;
+ }
+ scrollToEnd = false;
+ return GUIScrollList::NotifyTouch(state, x, y);
+}
+
+size_t GUIConsole::GetItemCount()
+{
+ return rConsole.size();
+}
+
+void GUIConsole::RenderItem(size_t itemindex, int yPos, bool selected)
+{
+ // Set the color for the font
+ if (rConsoleColor[itemindex] == "normal") {
+ gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
+ } else {
+ COLOR FontColor;
+ std::string color = rConsoleColor[itemindex];
+ ConvertStrToColor(color, &FontColor);
+ FontColor.alpha = 255;
+ gr_color(FontColor.red, FontColor.green, FontColor.blue, FontColor.alpha);
+ }
+
+ // render text
+ const char* text = rConsole[itemindex].c_str();
+ gr_textEx(mRenderX, yPos, text, mFont->GetResource());
+}
+
+void GUIConsole::NotifySelect(size_t item_selected)
+{
+ // do nothing - console ignores selections
+}
diff --git a/gui/devices/1080x1920/res/fonts/Roboto-Condensed-40.dat b/gui/devices/1080x1920/res/fonts/Roboto-Condensed-40.dat
new file mode 100644
index 000000000..ff23add82
--- /dev/null
+++ b/gui/devices/1080x1920/res/fonts/Roboto-Condensed-40.dat
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/back-icon.png b/gui/devices/1080x1920/res/images/back-icon.png
new file mode 100644
index 000000000..85c6a5d68
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/back-icon.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/checkbox_checked.png b/gui/devices/1080x1920/res/images/checkbox_checked.png
new file mode 100644
index 000000000..65d0b34da
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/checkbox_checked.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/checkbox_empty.png b/gui/devices/1080x1920/res/images/checkbox_empty.png
new file mode 100644
index 000000000..89b4c9627
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/checkbox_empty.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/cursor.png b/gui/devices/1080x1920/res/images/cursor.png
new file mode 100644
index 000000000..32c8ae1ca
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/curtain.jpg b/gui/devices/1080x1920/res/images/curtain.jpg
new file mode 100644
index 000000000..269941d5e
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/curtain.jpg
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/file.png b/gui/devices/1080x1920/res/images/file.png
new file mode 100644
index 000000000..a69b61996
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/file.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/folder.png b/gui/devices/1080x1920/res/images/folder.png
new file mode 100644
index 000000000..fbea7a970
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/folder.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/home-icon.png b/gui/devices/1080x1920/res/images/home-icon.png
new file mode 100644
index 000000000..d6bc73d82
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/home-icon.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/indeterminate001.png b/gui/devices/1080x1920/res/images/indeterminate001.png
new file mode 100644
index 000000000..a205e91aa
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/indeterminate001.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/indeterminate002.png b/gui/devices/1080x1920/res/images/indeterminate002.png
new file mode 100644
index 000000000..f777408be
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/indeterminate002.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/indeterminate003.png b/gui/devices/1080x1920/res/images/indeterminate003.png
new file mode 100644
index 000000000..cbb597482
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/indeterminate003.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/indeterminate004.png b/gui/devices/1080x1920/res/images/indeterminate004.png
new file mode 100644
index 000000000..5ff77341d
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/indeterminate004.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/indeterminate005.png b/gui/devices/1080x1920/res/images/indeterminate005.png
new file mode 100644
index 000000000..7cc9abb4f
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/indeterminate005.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/indeterminate006.png b/gui/devices/1080x1920/res/images/indeterminate006.png
new file mode 100644
index 000000000..9eed17600
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/indeterminate006.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/keyboard1.png b/gui/devices/1080x1920/res/images/keyboard1.png
new file mode 100644
index 000000000..79a8b69cb
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/keyboard1.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/keyboard2.png b/gui/devices/1080x1920/res/images/keyboard2.png
new file mode 100644
index 000000000..63a5b6a19
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/keyboard2.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/keyboard3.png b/gui/devices/1080x1920/res/images/keyboard3.png
new file mode 100644
index 000000000..a646c7557
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/keyboard3.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/keyboard4.png b/gui/devices/1080x1920/res/images/keyboard4.png
new file mode 100644
index 000000000..3b2905adb
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/keyboard4.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/medium-button.png b/gui/devices/1080x1920/res/images/medium-button.png
new file mode 100644
index 000000000..a3bf30d58
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/medium-button.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/menu-button.png b/gui/devices/1080x1920/res/images/menu-button.png
new file mode 100644
index 000000000..36d3f0127
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/menu-button.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/minus-button.png b/gui/devices/1080x1920/res/images/minus-button.png
new file mode 100644
index 000000000..e2edbe45f
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/minus-button.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/plus-button.png b/gui/devices/1080x1920/res/images/plus-button.png
new file mode 100644
index 000000000..b67d9b928
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/plus-button.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/progress_empty.png b/gui/devices/1080x1920/res/images/progress_empty.png
new file mode 100644
index 000000000..d4ea0c2fe
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/progress_empty.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/progress_fill.png b/gui/devices/1080x1920/res/images/progress_fill.png
new file mode 100644
index 000000000..836e437ae
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/progress_fill.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/radio_empty.png b/gui/devices/1080x1920/res/images/radio_empty.png
new file mode 100644
index 000000000..9c2c66bb0
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/radio_empty.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/radio_selected.png b/gui/devices/1080x1920/res/images/radio_selected.png
new file mode 100644
index 000000000..8d05b9d48
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/radio_selected.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/slideout.png b/gui/devices/1080x1920/res/images/slideout.png
new file mode 100644
index 000000000..56a9ac2aa
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/slideout.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/slider-touch.png b/gui/devices/1080x1920/res/images/slider-touch.png
new file mode 100644
index 000000000..b3365afee
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/slider-touch.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/slider-used.png b/gui/devices/1080x1920/res/images/slider-used.png
new file mode 100644
index 000000000..229d9109e
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/slider-used.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/slider.png b/gui/devices/1080x1920/res/images/slider.png
new file mode 100644
index 000000000..1e034a621
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/slider.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/sort-button.png b/gui/devices/1080x1920/res/images/sort-button.png
new file mode 100644
index 000000000..c6783a15c
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/sort-button.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/twrplogo.png b/gui/devices/1080x1920/res/images/twrplogo.png
new file mode 100644
index 000000000..16b1b2a1c
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/twrplogo.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/images/unlock.png b/gui/devices/1080x1920/res/images/unlock.png
new file mode 100644
index 000000000..dc3894b76
--- /dev/null
+++ b/gui/devices/1080x1920/res/images/unlock.png
Binary files differ
diff --git a/gui/devices/1080x1920/res/ui.xml b/gui/devices/1080x1920/res/ui.xml
new file mode 100644
index 000000000..a611d0582
--- /dev/null
+++ b/gui/devices/1080x1920/res/ui.xml
@@ -0,0 +1,443 @@
+<?xml version="1.0"?>
+
+<recovery>
+ <details>
+ <resolution width="1080" height="1920" />
+ <author>TeamWin</author>
+ <title>Backup Naowz</title>
+ <description>Default basic theme</description>
+ <preview>preview.jpg</preview>
+ </details>
+
+ <include>
+ <xmlfile name="portrait.xml" />
+ </include>
+
+ <resources>
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="40" fallback="Roboto-Condensed-40" />
+ <resource name="fixed" type="font" filename="DroidSansMono.ttf" size="30" />
+ <resource name="twrplogo" type="image" filename="twrplogo" retainaspect="1" />
+ <resource name="main_button" type="image" filename="menu-button" />
+ <resource name="file_icon" type="image" filename="file" retainaspect="1" />
+ <resource name="folder_icon" type="image" filename="folder" retainaspect="1" />
+ <resource name="slideout" type="image" filename="slideout" retainaspect="1" />
+ <resource name="progress" type="animation" filename="indeterminate" />
+ <resource name="progress_empty" type="image" filename="progress_empty" />
+ <resource name="progress_full" type="image" filename="progress_fill" />
+ <resource name="checkbox_false" type="image" filename="checkbox_empty" retainaspect="1" />
+ <resource name="checkbox_true" type="image" filename="checkbox_checked" retainaspect="1" />
+ <resource name="radio_false" type="image" filename="radio_empty" retainaspect="1" />
+ <resource name="radio_true" type="image" filename="radio_selected" retainaspect="1" />
+ <resource name="medium_button" type="image" filename="medium-button" />
+ <resource name="sort_button" type="image" filename="sort-button" />
+ <resource name="minus_button" type="image" filename="minus-button" />
+ <resource name="plus_button" type="image" filename="plus-button" />
+ <resource name="home_icon" type="image" filename="home-icon" retainaspect="1" />
+ <resource name="back_icon" type="image" filename="back-icon" retainaspect="1" />
+ <resource name="slider" type="image" filename="slider" retainaspect="1" />
+ <resource name="slider-used" type="image" filename="slider-used" retainaspect="1" />
+ <resource name="slider-touch" type="image" filename="slider-touch" retainaspect="1" />
+ <resource name="unlock-icon" type="image" filename="unlock" retainaspect="1" />
+ <resource name="keyboard1" type="image" filename="keyboard1" />
+ <resource name="keyboard2" type="image" filename="keyboard2" />
+ <resource name="keyboard3" type="image" filename="keyboard3" />
+ <resource name="keyboard4" type="image" filename="keyboard4" />
+ <resource name="cursor" type="image" filename="cursor" retainaspect="1" />
+ </resources>
+
+ <variables>
+ <variable name="col1_x" value="10" />
+ <variable name="col2_x" value="565" />
+ <variable name="col_center_x" value="288" />
+ <variable name="col_center_medium_x" value="414" />
+ <variable name="center_x" value="540" />
+ <variable name="row1_y" value="255" />
+ <variable name="row2_y" value="615" />
+ <variable name="row3_y" value="975" />
+ <variable name="row4_y" value="1335" />
+ <variable name="col1_center_x" value="179" />
+ <variable name="col2_center_x" value="552" />
+ <variable name="row1_text2_y" value="310" />
+ <variable name="row2_text2_y" value="550" />
+ <variable name="row_queue_y" value="1140" />
+ <variable name="row1_header_y" value="180" />
+ <variable name="row1_text_y" value="255" />
+ <variable name="row2_text_y" value="330" />
+ <variable name="row3_text_y" value="405" />
+ <variable name="row4_text_y" value="480" />
+ <variable name="row5_text_y" value="555" />
+ <variable name="row6_text_y" value="630" />
+ <variable name="row7_text_y" value="705" />
+ <variable name="row8_text_y" value="780" />
+ <variable name="row9_text_y" value="855" />
+ <variable name="row10_text_y" value="930" />
+ <variable name="row11_text_y" value="1005" />
+ <variable name="row12_text_y" value="1080" />
+ <variable name="row13_text_y" value="1155" />
+ <variable name="row14_text_y" value="1230" />
+ <variable name="row15_text_y" value="1305" />
+ <variable name="row16_text_y" value="1380" />
+ <variable name="row17_text_y" value="1455" />
+ <variable name="row18_text_y" value="1530" />
+ <variable name="zip_status_y" value="922" />
+ <variable name="flash_list_height" value="500" />
+ <variable name="tz_selected_y" value="240" />
+ <variable name="tz_set_y" value="1500" />
+ <variable name="tz_current_y" value="1425" />
+ <variable name="system_ro_y" value="1770" />
+ <variable name="col_progressbar_x" value="351" />
+ <variable name="row_progressbar_y" value="1650" />
+ <variable name="col1_medium_x" value="10" />
+ <variable name="col2_medium_x" value="282" />
+ <variable name="col3_medium_x" value="545" />
+ <variable name="col4_medium_x" value="817" />
+ <variable name="row1_medium_y" value="195" />
+ <variable name="row2_medium_y" value="345" />
+ <variable name="row3_medium_y" value="392" />
+ <variable name="row4_medium_y" value="645" />
+ <variable name="row5_medium_y" value="795" />
+ <variable name="row6_medium_y" value="1260" />
+ <variable name="row7_medium_y" value="730" />
+ <variable name="slider_y" value="1575" />
+ <variable name="slider_text_y" value="1676" />
+ <variable name="button_text_color" value="#AAAAAA" />
+ <variable name="text_color" value="#FFFFFF" />
+ <variable name="text_success_color" value="#33B5E5" />
+ <variable name="text_fail_color" value="#FF0101" />
+ <variable name="highlight_color" value="#90909080" />
+ <variable name="caps_highlight_color" value="#33B5E580" />
+ <variable name="home_button_x" value="10" />
+ <variable name="home_button_y" value="1839" />
+ <variable name="back_button_x" value="1070" />
+ <variable name="back_button_y" value="1839" />
+ <variable name="sort_text_x" value="10" />
+ <variable name="sort_asc_text_y" value="1635" />
+ <variable name="sort_asc_button_y" value="1620" />
+ <variable name="sort_desc_text_y" value="1725" />
+ <variable name="sort_desc_button_y" value="1710" />
+ <variable name="sort_col1_button_x" value="390" />
+ <variable name="sort_col2_button_x" value="540" />
+ <variable name="sort_col3_button_x" value="690" />
+ <variable name="input_width" value="1060" />
+ <variable name="input_height" value="75" />
+ <variable name="input_background_color" value="#303030" />
+ <variable name="input_cursor_color" value="#33B5E5" />
+ <variable name="input_cursor_width" value="4" />
+ <variable name="console_x" value="0" />
+ <variable name="console_width" value="1080" />
+ <variable name="console_foreground" value="#A0A0A0" />
+ <variable name="warning" value="#F8F8A0" />
+ <variable name="error" value="#FF4040" />
+ <variable name="highlight" value="#33B5E5" />
+ <variable name="console_background" value="#303030" />
+ <variable name="console_scroll" value="#303030" />
+ <variable name="console_action_height" value="705" />
+ <variable name="console_install_height" value="900" />
+ <variable name="console_installdone_height" value="660" />
+ <variable name="fileselector_x" value="5" />
+ <variable name="fileselector_width" value="1070" />
+ <variable name="fileselector_install_height" value="1170" />
+ <variable name="fileselector_header_background" value="#202020" />
+ <variable name="fileselector_header_textcolor" value="#AAAAAA" />
+ <variable name="fileselector_header_separatorcolor" value="#33B5E5" />
+ <variable name="fileselector_header_separatorheight" value="4" />
+ <variable name="fileselector_separatorcolor" value="#505050" />
+ <variable name="fileselector_separatorheight" value="3" />
+ <variable name="fileselector_background" value="#303030" />
+ <variable name="fileselector_highlight_color" value="#505050" />
+ <variable name="fileselector_highlight_font_color" value="#33B5E5" />
+ <variable name="fileselector_spacing" value="48" />
+ <variable name="fastscroll_linecolor" value="#50505080" />
+ <variable name="fastscroll_rectcolor" value="#33B5E580" />
+ <variable name="fastscroll_w" value="90" />
+ <variable name="fastscroll_linew" value="3" />
+ <variable name="fastscroll_rectw" value="21" />
+ <variable name="fastscroll_recth" value="60" />
+ <variable name="listbox_x" value="5" />
+ <variable name="listbox_width" value="1070" />
+ <variable name="listbox_tz_height" value="885" />
+ <variable name="listbox_background" value="#303030" />
+ <variable name="listbox_spacing" value="24" />
+ <variable name="sd_plus_x" value="525" />
+ <variable name="sdext_text_x" value="165" />
+ <variable name="sdext_text_y" value="270" />
+ <variable name="sdswap_button_y" value="390" />
+ <variable name="sdswap_text_x" value="165" />
+ <variable name="sdswap_text_y" value="405" />
+ <variable name="sdfilesystem_text_y" value="510" />
+ <variable name="sdfilesystem_button_y" value="570" />
+ <variable name="lock_y" value="700" />
+ <variable name="filemanager_select_x" value="840" />
+ <variable name="filemanager_select_y" value="1620" />
+ <variable name="backup_name_y" value="825" />
+ <variable name="terminal_console_height" value="1050" />
+ <variable name="terminal_text_y" value="1095" />
+ <variable name="terminal_button_y" value="1050" />
+ <variable name="row_dst_text_y" value="1080" />
+ <variable name="row_offset_text_y" value="1155" />
+ <variable name="row_offset_medium_y" value="1260" />
+ <variable name="button_fill_color" value="#303030" />
+ <variable name="button_fill_full_width" value="1060" />
+ <variable name="button_fill_main_width" value="505" />
+ <variable name="button_fill_main_height" value="324" />
+ <variable name="button_fill_half_height" value="162" />
+ <variable name="button_fill_quarter_height" value="81" />
+ <variable name="backup_list_height" value="780" />
+ <variable name="backup_button_row1" value="1118" />
+ <variable name="backup_button_row2" value="1220" />
+ <variable name="mount_list_height" value="1035" />
+ <variable name="mount_storage_row" value="1240" />
+ <variable name="storage_list_height" value="1000" />
+ <variable name="wipe_list_height" value="1105" />
+ <variable name="wipe_button_row1" value="1350" />
+ <variable name="wipe_button_y" value="975" />
+ <variable name="slidervalue_w" value="1060" />
+ <variable name="slidervalue_line_clr" value="#FFFFFF" />
+ <variable name="slidervalue_slider_clr" value="#33B5E5" />
+ <variable name="slidervalue_lineh" value="3" />
+ <variable name="slidervalue_padding" value="30" />
+ <variable name="slidervalue_sliderw" value="15" />
+ <variable name="slidervalue_sliderh" value="90" />
+ <variable name="pattern_x" value="216" />
+ <variable name="pattern_y" value="508" />
+ <variable name="pattern_width" value="648" />
+ <variable name="pattern_dot_color" value="#33B5E5" />
+ <variable name="pattern_dot_color_active" value="#FFFFFF" />
+ <variable name="pattern_dot_radius" value="23" />
+ <variable name="pattern_line_color" value="#33B5E5" />
+ <variable name="pattern_line_width" value="18" />
+ </variables>
+
+ <mousecursor>
+ <placement w="15" h="15" />
+ <background color="#FFFF00FF" resource="cursor" />
+ <speed multiplier="2.5" />
+ </mousecursor>
+
+ <templates>
+ <template name="header">
+ <background color="#000000FF" />
+
+ <object type="fill" color="%button_fill_color%">
+ <placement x="0" y="0" w="1080" h="176" />
+ </object>
+
+ <object type="fill" color="%highlight%">
+ <placement x="0" y="176" w="1080" h="4" />
+ </object>
+
+ <object type="image">
+ <image resource="twrplogo" />
+ <placement x="85" y="85" placement="4" />
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="180" y="15" />
+ <text>Team Win Recovery Project v%tw_version%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <condition var1="tw_simulate_actions" var2="1" />
+ <font resource="font" />
+ <placement x="180" y="60" />
+ <text>SIMULATING ACTIONS</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="180" y="114" />
+ <text>%tw_time%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="405" y="114" />
+ <conditions>
+ <condition var1="tw_no_battery_percent" var2="0" />
+ <condition var1="tw_battery" op="&gt;" var2="0" />
+ <condition var1="tw_battery" op="&lt;" var2="101" />
+ </conditions>
+ <text>Battery: %tw_battery%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="760" y="114" />
+ <conditions>
+ <condition var1="tw_no_cpu_temp" var2="0" />
+ </conditions>
+ <text>CPU: %tw_cpu_temp% C</text>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%home_button_x%" y="%home_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="home_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">home</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%back_button_x%" y="%back_button_y%" placement="1" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="back_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">back</action>
+ </object>
+
+ <object type="action">
+ <touch key="power" />
+ <action function="overlay">lock</action>
+ </object>
+
+ <object type="action">
+ <touch key="power+voldown" />
+ <action function="screenshot" />
+ </object>
+ </template>
+
+ <template name="progress_bar">
+ <object type="progressbar">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource empty="progress_empty" full="progress_full" />
+ <data name="ui_progress" />
+ </object>
+
+ <object type="animation">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource name="progress" />
+ <speed fps="15" render="2" />
+ <loop frame="1" />
+ </object>
+ </template>
+
+ <template name="sort_options">
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="%sort_text_x%" y="%sort_asc_text_y%" />
+ <text>Sort Ascending:</text>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col1_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=1</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col2_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=2</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col3_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=3</action>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="%sort_text_x%" y="%sort_desc_text_y%" />
+ <text>Sort Descending:</text>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col1_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-1</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col2_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-2</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col3_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-3</action>
+ </object>
+ </template>
+
+ <template name="action_page_console">
+ <object type="console">
+ <placement x="0" y="%row2_y%" w="1080" h="705" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="footer">
+ <object type="console">
+ <slideout resource="slideout" x="%center_x%" y="1841" placement="5" />
+ <placement x="%console_x%" y="0" w="%console_width%" h="1841" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="keyboardtemplate">
+ <object type="keyboard">
+ <placement x="0" y="1200" />
+ <layout resource1="keyboard1" resource2="keyboard2" resource3="keyboard3" resource4="keyboard4" />
+ <highlight color="%highlight_color%" />
+ <capshighlight color="%caps_highlight_color%" />
+ <layout1>
+ <keysize height="161" width="108" />
+ <row1 key01="q" long01="1" key02="w" long02="2" key03="e" long03="3" key04="r" long04="4" key05="t" long05="5" key06="y" long06="6" key07="u" long07="7" key08="i" long08="8" key09="o" long09="9" key10="p" long10="0" />
+ <row2 key01="162:a" long01="@" key02="s" long02="#" key03="d" long03="$" key04="f" long04="%" key05="g" long05="&amp;" key06="h" long06="*" key07="j" long07="-" key08="k" long08="+" key09="162:l" long09="_" />
+ <row3 key01="162:layout2" key02="z" long02="!" key03="x" key04="c" long04="'" key05="v" long05=":" key06="b" long06=";" key07="n" long07="/" key08="m" long08="?" key09="162:c:8" />
+ <row4 key01="162:layout3" key02="108:c:47" key03="108:" key04="432: " key05="." key06="162:action" />
+ </layout1>
+ <layout2>
+ <keysize height="161" width="108" capslock="0" revert_layout="1" />
+ <row1 key01="Q" long01="1" key02="W" long02="2" key03="E" long03="3" key04="R" long04="4" key05="T" long05="5" key06="Y" long06="6" key07="U" long07="7" key08="I" long08="8" key09="O" long09="9" key10="P" long10="0" />
+ <row2 key01="162:A" long01="@" key02="S" long02="#" key03="D" long03="$" key04="F" long04="%" key05="G" long05="&amp;" key06="H" long06="*" key07="J" long07="-" key08="K" long08="+" key09="162:L" long09="_" />
+ <row3 key01="162:layout1" key02="Z" long02="!" key03="X" key04="C" long04="'" key05="V" long05=":" key06="B" long06=";" key07="N" long07="/" key08="M" long08="?" key09="162:c:8" />
+ <row4 key01="162:layout3" key02="/" key03="108:" key04="432: " key05="." key06="162:action" />
+ </layout2>
+ <layout3>
+ <keysize height="161" width="108" />
+ <row1 key01="1" key02="2" key03="3" key04="4" key05="5" key06="6" key07="7" key08="8" key09="9" key10="0" />
+ <row2 key01="@" key02="#" key03="$" key04="%" key05="&amp;" key06="*" key07="-" key08="+" key09="(" key10=")" />
+ <row3 key01="162:layout4" key02="!" key03="108:c:34" key04="'" key05=":" key06=";" key07="/" key08="?" key09="162:c:8" />
+ <row4 key01="162:layout1" key02="," key03="108:" key04="432: " key05="." key06="162:action" />
+ </layout3>
+ <layout4>
+ <keysize height="161" width="108" />
+ <row1 key01="~" key02="`" key03="|" key04="108:" key05="108:" key06="108:" key07="%" key08="108:" key09="{" key10="}" />
+ <row2 key01="108:" key02="108:" key03="108:" key04="108:" key05="108:" key06="^" key07="_" key08="=" key09="[" key10="]" />
+ <row3 key01="162:layout3" key02="108:" key03="108:" key04="108:" key05="108:" key06="\" key07="&lt;" key08="&gt;" key09="162:c:8" />
+ <row4 key01="162:layout1" key02="108:c:34" key03="108:" key04="432: " key05="." key06="162:action" />
+ </layout4>
+ </object>
+ </template>
+ </templates>
+</recovery>
diff --git a/gui/devices/1920x1200/res/fonts/Roboto-Regular-30.dat b/gui/devices/1920x1200/res/fonts/Roboto-Regular-30.dat
new file mode 100644
index 000000000..9f8082ccc
--- /dev/null
+++ b/gui/devices/1920x1200/res/fonts/Roboto-Regular-30.dat
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/back-icon.png b/gui/devices/1920x1200/res/images/back-icon.png
new file mode 100644
index 000000000..94dd69951
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/back-icon.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/button.png b/gui/devices/1920x1200/res/images/button.png
new file mode 100644
index 000000000..e1b49fc57
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/button.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/checkbox_checked.png b/gui/devices/1920x1200/res/images/checkbox_checked.png
new file mode 100644
index 000000000..cac9a30ee
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/checkbox_checked.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/checkbox_empty.png b/gui/devices/1920x1200/res/images/checkbox_empty.png
new file mode 100644
index 000000000..ee01fa852
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/checkbox_empty.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/console-icon.png b/gui/devices/1920x1200/res/images/console-icon.png
new file mode 100644
index 000000000..c1f4d7165
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/console-icon.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/console-toggle.png b/gui/devices/1920x1200/res/images/console-toggle.png
new file mode 100644
index 000000000..2495165fc
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/console-toggle.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/cursor.png b/gui/devices/1920x1200/res/images/cursor.png
new file mode 100644
index 000000000..32c8ae1ca
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/curtain.jpg b/gui/devices/1920x1200/res/images/curtain.jpg
new file mode 100644
index 000000000..409664c6c
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/curtain.jpg
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/file.png b/gui/devices/1920x1200/res/images/file.png
new file mode 100644
index 000000000..c77a1f483
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/file.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/folder.png b/gui/devices/1920x1200/res/images/folder.png
new file mode 100644
index 000000000..2770f0a24
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/folder.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/home-icon.png b/gui/devices/1920x1200/res/images/home-icon.png
new file mode 100644
index 000000000..8c1dde3c5
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/home-icon.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/indeterminate001.png b/gui/devices/1920x1200/res/images/indeterminate001.png
new file mode 100755
index 000000000..ea2b5e2ab
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/indeterminate001.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/indeterminate002.png b/gui/devices/1920x1200/res/images/indeterminate002.png
new file mode 100755
index 000000000..f59b298ee
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/indeterminate002.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/indeterminate003.png b/gui/devices/1920x1200/res/images/indeterminate003.png
new file mode 100755
index 000000000..cc6d7b535
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/indeterminate003.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/indeterminate004.png b/gui/devices/1920x1200/res/images/indeterminate004.png
new file mode 100755
index 000000000..9483117d6
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/indeterminate004.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/indeterminate005.png b/gui/devices/1920x1200/res/images/indeterminate005.png
new file mode 100755
index 000000000..850de0f88
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/indeterminate005.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/indeterminate006.png b/gui/devices/1920x1200/res/images/indeterminate006.png
new file mode 100755
index 000000000..e5194b39d
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/indeterminate006.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/keyboard1.png b/gui/devices/1920x1200/res/images/keyboard1.png
new file mode 100644
index 000000000..8ee241671
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/keyboard1.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/keyboard2.png b/gui/devices/1920x1200/res/images/keyboard2.png
new file mode 100644
index 000000000..259bfecf5
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/keyboard2.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/keyboard3.png b/gui/devices/1920x1200/res/images/keyboard3.png
new file mode 100644
index 000000000..aaebd3084
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/keyboard3.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/keyboard4.png b/gui/devices/1920x1200/res/images/keyboard4.png
new file mode 100644
index 000000000..1fe856566
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/keyboard4.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/medium-button.png b/gui/devices/1920x1200/res/images/medium-button.png
new file mode 100644
index 000000000..b4eb49324
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/medium-button.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/mediumwide-button.png b/gui/devices/1920x1200/res/images/mediumwide-button.png
new file mode 100644
index 000000000..3ca436eb2
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/mediumwide-button.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/minus-button.png b/gui/devices/1920x1200/res/images/minus-button.png
new file mode 100644
index 000000000..8dc17bfe6
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/minus-button.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/plus-button.png b/gui/devices/1920x1200/res/images/plus-button.png
new file mode 100644
index 000000000..05b34392c
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/plus-button.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/progress_empty.png b/gui/devices/1920x1200/res/images/progress_empty.png
new file mode 100644
index 000000000..ff02df652
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/progress_empty.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/progress_fill.png b/gui/devices/1920x1200/res/images/progress_fill.png
new file mode 100644
index 000000000..84a582885
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/progress_fill.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/radio_empty.png b/gui/devices/1920x1200/res/images/radio_empty.png
new file mode 100644
index 000000000..c77130019
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/radio_empty.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/radio_selected.png b/gui/devices/1920x1200/res/images/radio_selected.png
new file mode 100644
index 000000000..d3b22789a
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/radio_selected.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/slider-touch.png b/gui/devices/1920x1200/res/images/slider-touch.png
new file mode 100644
index 000000000..8a21a3b74
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/slider-touch.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/slider-used.png b/gui/devices/1920x1200/res/images/slider-used.png
new file mode 100644
index 000000000..4963ff5ae
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/slider-used.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/slider.png b/gui/devices/1920x1200/res/images/slider.png
new file mode 100644
index 000000000..dfeea6eda
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/slider.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/sort-button.png b/gui/devices/1920x1200/res/images/sort-button.png
new file mode 100644
index 000000000..b1f82182f
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/sort-button.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/twrplogo.png b/gui/devices/1920x1200/res/images/twrplogo.png
new file mode 100644
index 000000000..6847db69b
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/twrplogo.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/images/unlock.png b/gui/devices/1920x1200/res/images/unlock.png
new file mode 100644
index 000000000..6ca95d125
--- /dev/null
+++ b/gui/devices/1920x1200/res/images/unlock.png
Binary files differ
diff --git a/gui/devices/1920x1200/res/ui.xml b/gui/devices/1920x1200/res/ui.xml
new file mode 100644
index 000000000..cac02796e
--- /dev/null
+++ b/gui/devices/1920x1200/res/ui.xml
@@ -0,0 +1,456 @@
+<?xml version="1.0"?>
+
+<recovery>
+ <details>
+ <resolution width="1920" height="1200" />
+ <author>TeamWin</author>
+ <title>Backup Naowz</title>
+ <description>Default basic theme</description>
+ <preview>preview.jpg</preview>
+ </details>
+
+ <include>
+ <xmlfile name="landscape.xml" />
+ </include>
+
+ <resources>
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="30" fallback="Roboto-Regular-30" />
+ <resource name="fixed" type="font" filename="DroidSansMono.ttf" size="22" />
+ <resource name="twrplogo" type="image" filename="twrplogo" retainaspect="1" />
+ <resource name="main_button" type="image" filename="button" />
+ <resource name="file_icon" type="image" filename="file" retainaspect="1" />
+ <resource name="folder_icon" type="image" filename="folder" retainaspect="1" />
+ <resource name="progress" type="animation" filename="indeterminate" />
+ <resource name="progress_empty" type="image" filename="progress_empty" />
+ <resource name="progress_full" type="image" filename="progress_fill" />
+ <resource name="checkbox_false" type="image" filename="checkbox_empty" retainaspect="1" />
+ <resource name="checkbox_true" type="image" filename="checkbox_checked" retainaspect="1" />
+ <resource name="radio_false" type="image" filename="radio_empty" retainaspect="1" />
+ <resource name="radio_true" type="image" filename="radio_selected" retainaspect="1" />
+ <resource name="medium_button" type="image" filename="medium-button" />
+ <resource name="mediumwide_button" type="image" filename="mediumwide-button" />
+ <resource name="sort_button" type="image" filename="sort-button" />
+ <resource name="minus_button" type="image" filename="minus-button" />
+ <resource name="plus_button" type="image" filename="plus-button" />
+ <resource name="home_icon" type="image" filename="home-icon" retainaspect="1" />
+ <resource name="back_icon" type="image" filename="back-icon" retainaspect="1" />
+ <resource name="console_button" type="image" filename="console-toggle" retainaspect="1" />
+ <resource name="slider" type="image" filename="slider" retainaspect="1" />
+ <resource name="slider-used" type="image" filename="slider-used" retainaspect="1" />
+ <resource name="slider-touch" type="image" filename="slider-touch" retainaspect="1" />
+ <resource name="unlock-icon" type="image" filename="unlock" retainaspect="1" />
+ <resource name="keyboard1" type="image" filename="keyboard1" />
+ <resource name="keyboard2" type="image" filename="keyboard2" />
+ <resource name="keyboard3" type="image" filename="keyboard3" />
+ <resource name="keyboard4" type="image" filename="keyboard4" />
+ <resource name="cursor" type="image" filename="cursor" retainaspect="1" />
+ </resources>
+
+ <variables>
+ <variable name="col1_x" value="210" />
+ <variable name="col2_x" value="590" />
+ <variable name="col3_x" value="970" />
+ <variable name="col4_x" value="1350" />
+ <variable name="row1_y" value="220" />
+ <variable name="row2_y" value="680" />
+ <variable name="col_center_x" value="780" />
+ <variable name="center_x" value="960" />
+ <variable name="screen_width" value="1920" />
+ <variable name="screen_height" value="1200" />
+ <variable name="col_progressbar_x" value="771" />
+ <variable name="row_progressbar_y" value="1100" />
+ <variable name="col1_medium_x" value="570" />
+ <variable name="col2_medium_x" value="770" />
+ <variable name="col3_medium_x" value="970" />
+ <variable name="col4_medium_x" value="1170" />
+ <variable name="row1_medium_y" value="105" />
+ <variable name="row2_medium_y" value="365" />
+ <variable name="row3_medium_y" value="245" />
+ <variable name="row4_medium_y" value="720" />
+ <variable name="row5_medium_y" value="700" />
+ <variable name="row1_text_y" value="90" />
+ <variable name="row2_text_y" value="140" />
+ <variable name="row3_text_y" value="190" />
+ <variable name="row4_text_y" value="240" />
+ <variable name="row5_text_y" value="290" />
+ <variable name="row6_text_y" value="340" />
+ <variable name="row7_text_y" value="390" />
+ <variable name="row8_text_y" value="440" />
+ <variable name="row9_text_y" value="490" />
+ <variable name="row10_text_y" value="540" />
+ <variable name="row11_text_y" value="590" />
+ <variable name="row12_text_y" value="640" />
+ <variable name="row13_text_y" value="690" />
+ <variable name="row14_text_y" value="740" />
+ <variable name="row15_text_y" value="790" />
+ <variable name="row16_text_y" value="840" />
+ <variable name="row17_text_y" value="890" />
+ <variable name="row18_text_y" value="940" />
+ <variable name="row_offsetmedium_y" value="775" />
+ <variable name="home_button_x" value="1620" />
+ <variable name="home_button_y" value="5" />
+ <variable name="back_button_x" value="1720" />
+ <variable name="back_button_y" value="5" />
+ <variable name="console_button_x" value="1820" />
+ <variable name="console_button_y" value="5" />
+ <variable name="nandcheck_col1" value="328" />
+ <variable name="nandcheck_col2" value="800" />
+ <variable name="nandcheck_row1" value="200" />
+ <variable name="nandcheck_row2" value="275" />
+ <variable name="nandcheck_row3" value="350" />
+ <variable name="nandcheck_row4" value="425" />
+ <variable name="nandcheck_row5" value="500" />
+ <variable name="nandcheck_row6" value="575" />
+ <variable name="nandcheck_row7" value="650" />
+ <variable name="nandcheck_row8" value="725" />
+ <variable name="button_text_color" value="#AAAAAA" />
+ <variable name="text_color" value="#A0A0A0" />
+ <variable name="text_success_color" value="#33B5E5" />
+ <variable name="text_fail_color" value="#FF0101" />
+ <variable name="highlight_color" value="#90909080" />
+ <variable name="caps_highlight_color" value="#33B5E580" />
+ <variable name="slider_y" value="1000" />
+ <variable name="slider_text_y" value="1075" />
+ <variable name="sort_text_x" value="400" />
+ <variable name="sort_asc_text_y" value="1045" />
+ <variable name="sort_asc_button_y" value="1040" />
+ <variable name="sort_desc_text_y" value="1105" />
+ <variable name="sort_desc_button_y" value="1100" />
+ <variable name="sort_col1_button_x" value="670" />
+ <variable name="sort_col2_button_x" value="770" />
+ <variable name="sort_col3_button_x" value="870" />
+ <variable name="col1_sdext_x" value="720" />
+ <variable name="col2_sdext_x" value="1100" />
+ <variable name="row1_sdext_y" value="180" />
+ <variable name="row2_sdext_y" value="265" />
+ <variable name="row_extsize_y" value="175" />
+ <variable name="row_swapsize_y" value="260" />
+ <variable name="input_x" value="50" />
+ <variable name="input_width" value="1820" />
+ <variable name="input_height" value="50" />
+ <variable name="input_background_color" value="#303030" />
+ <variable name="input_cursor_color" value="#33B5E5" />
+ <variable name="input_cursor_width" value="3" />
+ <variable name="console_x" value="50" />
+ <variable name="console_width" value="1820" />
+ <variable name="console_foreground" value="#A0A0A0" />
+ <variable name="warning" value="#F8F8A0" />
+ <variable name="error" value="#FF4040" />
+ <variable name="highlight" value="#33B5E5" />
+ <variable name="console_background" value="#303030" />
+ <variable name="console_scroll" value="#303030" />
+ <variable name="console_action_height" value="320" />
+ <variable name="console_install_height" value="440" />
+ <variable name="console_installdone_height" value="300" />
+ <variable name="fileselector_folder_x" value="50" />
+ <variable name="fileselector_folder_width" value="610" />
+ <variable name="fileselector_folderonly_width" value="800" />
+ <variable name="fileselector_file_x" value="700" />
+ <variable name="fileselector_file_width" value="1170" />
+ <variable name="fileselector_install_y" value="205" />
+ <variable name="fileselector_install_height" value="800" />
+ <variable name="fileselector_header_background" value="#202020" />
+ <variable name="fileselector_header_textcolor" value="#AAAAAA" />
+ <variable name="fileselector_header_separatorcolor" value="#33B5E5" />
+ <variable name="fileselector_header_separatorheight" value="3" />
+ <variable name="fileselector_separatorcolor" value="#505050" />
+ <variable name="fileselector_separatorheight" value="2" />
+ <variable name="fileselector_background" value="#303030" />
+ <variable name="fileselector_highlight_color" value="#505050" />
+ <variable name="fileselector_highlight_font_color" value="#33B5E5" />
+ <variable name="fileselector_spacing" value="18" />
+ <variable name="fastscroll_linecolor" value="#50505080" />
+ <variable name="fastscroll_rectcolor" value="#33B5E580" />
+ <variable name="fastscroll_w" value="60" />
+ <variable name="fastscroll_linew" value="3" />
+ <variable name="fastscroll_rectw" value="15" />
+ <variable name="fastscroll_recth" value="40" />
+ <variable name="zipstorage_text_y" value="130" />
+ <variable name="listbox_x" value="560" />
+ <variable name="listbox_y" value="150" />
+ <variable name="listbox_width" value="800" />
+ <variable name="listbox_tz_height" value="400" />
+ <variable name="listbox_background" value="#303030" />
+ <variable name="listbox_spacing" value="18" />
+ <variable name="sd_plus_x" value="408" />
+ <variable name="lock_y" value="300" />
+ <variable name="filemanager_select_x" value="1500" />
+ <variable name="filemanager_select_y" value="980" />
+ <variable name="backup_name_text_y" value="440" />
+ <variable name="backup_name_button_y" value="390" />
+ <variable name="col_right_x" value="1870" />
+ <variable name="cancel_button_y" value="240" />
+ <variable name="terminal_console_y" value="0" />
+ <variable name="terminal_console_height" value="610" />
+ <variable name="terminal_text_y" value="624" />
+ <variable name="terminal_button_y" value="615" />
+ <variable name="terminal_input_width" value="1550" />
+ <variable name="button_fill_color" value="#303030" />
+ <variable name="button_fill_full_width" value="960" />
+ <variable name="button_fill_main_width" value="900" />
+ <variable name="button_fill_main_height" value="240" />
+ <variable name="button_fill_half_height" value="80" />
+ <variable name="button_fill_quarter_height" value="60" />
+ <variable name="button_full_center_x" value="480" />
+ <variable name="flash_list_height" value="300" />
+ <variable name="backup_list_x" value="50" />
+ <variable name="backup_list_y" value="160" />
+ <variable name="backup_list_width" value="900" />
+ <variable name="backup_list_height" value="660" />
+ <variable name="backup_storage_y" value="405" />
+ <variable name="backup_encrypt_y" value="495" />
+ <variable name="restore_list_y" value="190" />
+ <variable name="restore_list_height" value="600" />
+ <variable name="mount_list_height" value="900" />
+ <variable name="mount_storage_row" value="850" />
+ <variable name="wipe_list_height" value="850" />
+ <variable name="wipe_button_y" value="375" />
+ <variable name="slidervalue_x" value="540" />
+ <variable name="slidervalue_w" value="960" />
+ <variable name="slidervalue_line_clr" value="#FFFFFF" />
+ <variable name="slidervalue_slider_clr" value="#33B5E5" />
+ <variable name="slidervalue_lineh" value="3" />
+ <variable name="slidervalue_padding" value="0" />
+ <variable name="slidervalue_sliderw" value="20" />
+ <variable name="slidervalue_sliderh" value="80" />
+ <variable name="pattern_x" value="480" />
+ <variable name="pattern_y" value="240" />
+ <variable name="pattern_width" value="720" />
+ <variable name="pattern_dot_color" value="#33B5E5" />
+ <variable name="pattern_dot_color_active" value="#FFFFFF" />
+ <variable name="pattern_dot_radius" value="23" />
+ <variable name="pattern_line_color" value="#33B5E5" />
+ <variable name="pattern_line_width" value="18" />
+ </variables>
+
+ <mousecursor>
+ <placement w="15" h="15" />
+ <background color="#FFFF00FF" resource="cursor" />
+ <speed multiplier="2.5" />
+ </mousecursor>
+
+ <templates>
+ <template name="header">
+ <background color="#000000FF" />
+
+ <object type="fill" color="%button_fill_color%">
+ <placement x="0" y="0" w="1920" h="87" />
+ </object>
+
+ <object type="fill" color="%highlight%">
+ <placement x="0" y="87" w="1920" h="3" />
+ </object>
+
+ <object type="image">
+ <image resource="twrplogo" />
+ <placement x="55" y="45" placement="4" />
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="100" y="5" />
+ <text>Team Win Recovery Project v%tw_version%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="100" y="40" />
+ <conditions>
+ <condition var1="tw_no_battery_percent" var2="0" />
+ <condition var1="tw_battery" op="&gt;" var2="0" />
+ <condition var1="tw_battery" op="&lt;" var2="101" />
+ </conditions>
+ <text>Battery Level: %tw_battery%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="600" y="40" />
+ <text>%tw_time%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="1150" y="40" />
+ <conditions>
+ <condition var1="tw_no_cpu_temp" var2="0" />
+ </conditions>
+ <text>CPU: %tw_cpu_temp% C</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <condition var1="tw_simulate_actions" var2="1" />
+ <font resource="font" />
+ <placement x="750" y="40" />
+ <text>SIMULATING ACTIONS</text>
+ </object>
+
+ <object type="button">
+ <placement x="%home_button_x%" y="%home_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="home_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">home</action>
+ </object>
+
+ <object type="button">
+ <placement x="%back_button_x%" y="%back_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="back_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">back</action>
+ </object>
+
+ <object type="action">
+ <touch key="power" />
+ <action function="overlay">lock</action>
+ </object>
+
+ <object type="action">
+ <touch key="power+voldown" />
+ <action function="screenshot" />
+ </object>
+ </template>
+
+ <template name="progress_bar">
+ <object type="progressbar">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource empty="progress_empty" full="progress_full" />
+ <data name="ui_progress" />
+ </object>
+
+ <object type="animation">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource name="progress" />
+ <speed fps="15" render="6" />
+ <loop frame="1" />
+ </object>
+ </template>
+
+ <template name="sort_options">
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="%sort_text_x%" y="%sort_asc_text_y%" />
+ <text>Sort Ascending:</text>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col1_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col2_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=2</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col3_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=3</action>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="%sort_text_x%" y="%sort_desc_text_y%" />
+ <text>Sort Descending:</text>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col1_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col2_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-2</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col3_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-3</action>
+ </object>
+ </template>
+
+ <template name="flash_zip_console">
+ <object type="console">
+ <placement x="%console_x%" y="140" w="%console_width%" h="700" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="action_page_console">
+ <object type="console">
+ <placement x="%console_x%" y="400" w="%console_width%" h="600" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="footer">
+ <object type="console">
+ <slideout resource="console_button" x="%console_button_x%" y="%console_button_y%" />
+ <placement x="%console_x%" y="150" w="%console_width%" h="1000" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="keyboardtemplate">
+ <object type="keyboard">
+ <placement x="0" y="684" />
+ <layout resource1="keyboard1" resource2="keyboard2" resource3="keyboard3" resource4="keyboard4" />
+ <highlight color="%highlight_color%" />
+ <capshighlight color="%caps_highlight_color%" />
+ <layout1>
+ <keysize height="129" width="159" />
+ <row1 key01="153:" key02="q" long02="1" key03="w" long03="2" key04="e" long04="3" key05="r" long05="4" key06="t" long06="5" key07="y" long07="6" key08="u" long08="7" key09="i" long09="8" key10="o" long10="9" key11="p" long11="0" key12="177:c:8" />
+ <row2 key01="213:layout3" key02="156:a" key03="156:s" key04="156:d" key05="156:f" key06="156:g" key07="156:h" key08="156:j" key09="k" key10="156:l" key11="303:action" />
+ <row3 key01="269:layout2" key02="154:z" key03="154:x" key04="154:c" key05="154:v" key06="154:b" key07="154:n" key08="154:m" key09="154:," long09="!" key10="154:." long10="?" key11="265:layout2" />
+ <row4 key01="600:" key02="720: " key03="/" long03=":" key04="-" long04="_" />
+ </layout1>
+ <layout2>
+ <keysize height="129" width="159" capslock="0" revert_layout="1" />
+ <row1 key01="153:" key02="Q" long02="1" key03="W" long03="2" key04="E" long04="3" key05="R" long05="4" key06="T" long06="5" key07="Y" long07="6" key08="U" long08="7" key09="I" long09="8" key10="O" long10="9" key11="P" long11="0" key12="177:c:8" />
+ <row2 key01="213:layout3" key02="156:A" key03="156:S" key04="156:D" key05="156:F" key06="156:G" key07="156:H" key08="156:J" key09="156:K" key10="156:L" key11="303:action" />
+ <row3 key01="269:layout1" key02="154:Z" key03="154:X" key04="154:C" key05="154:V" key06="154:B" key07="154:N" key08="154:M" key09="154:!" key10="154:?" key11="265:layout1" />
+ <row4 key01="600:" key02="720: " key03=":" key04="_" />
+ </layout2>
+ <layout3>
+ <keysize height="129" width="159" />
+ <row1 key01="153:" key02="1" key03="2" key04="3" key05="4" key06="5" key07="6" key08="7" key09="8" key10="9" key11="0" key12="177:c:8" />
+ <row2 key01="213:layout1" key02="156:#" key03="156:$" key04="156:%" key05="156:&amp;" key06="156:*" key07="156:-" key08="156:+" key09="156:(" key10="156:)" key11="303:action" />
+ <row3 key01="269:layout4" key02="154:&lt;" key03="154:&gt;" key04="154:=" key05="154:'" key06="154:;" key07="154:," key08="154:." key09="154:!" key10="154:?" key11="265:layout4" />
+ <row4 key01="282:" key02="/" key03="@" key04="720: " key05="159:c:34" key06="_" />
+ </layout3>
+ <layout4>
+ <keysize height="129" width="159" />
+ <row1 key01="153:" key02="~" key03="`" key04="|" key05="159:" key06="159:" key07="159:" key08="159:" key09="159:" key10="159:" key11="159:" key12="177:c:8" />
+ <row2 key01="213:layout1" key02="156:" key03="156:" key04="156:" key05="156:" key06="156:^" key07="156:" key08="156:" key09="156:{" key10="156:}" key11="303:action" />
+ <row3 key01="269:layout3" key02="154:\" key03="154:" key04="154:" key05="154:" key06="154:" key07="154:[" key08="154:]" key09="154:!" key10="154:?" key11="265:layout3" />
+ <row4 key01="600:" key02="720: " />
+ </layout4>
+ </object>
+ </template>
+ </templates>
+</recovery>
diff --git a/gui/devices/320x320/res/fonts/Roboto-Condensed-14.dat b/gui/devices/320x320/res/fonts/Roboto-Condensed-14.dat
new file mode 100644
index 000000000..f7b174cb1
--- /dev/null
+++ b/gui/devices/320x320/res/fonts/Roboto-Condensed-14.dat
Binary files differ
diff --git a/gui/devices/320x320/res/images/back-icon.png b/gui/devices/320x320/res/images/back-icon.png
new file mode 100644
index 000000000..fa365f734
--- /dev/null
+++ b/gui/devices/320x320/res/images/back-icon.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/checkbox_checked.png b/gui/devices/320x320/res/images/checkbox_checked.png
new file mode 100644
index 000000000..81037cb70
--- /dev/null
+++ b/gui/devices/320x320/res/images/checkbox_checked.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/checkbox_empty.png b/gui/devices/320x320/res/images/checkbox_empty.png
new file mode 100644
index 000000000..94bb057f5
--- /dev/null
+++ b/gui/devices/320x320/res/images/checkbox_empty.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/cursor.png b/gui/devices/320x320/res/images/cursor.png
new file mode 100644
index 000000000..32c8ae1ca
--- /dev/null
+++ b/gui/devices/320x320/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/curtain.jpg b/gui/devices/320x320/res/images/curtain.jpg
new file mode 100644
index 000000000..0368a6574
--- /dev/null
+++ b/gui/devices/320x320/res/images/curtain.jpg
Binary files differ
diff --git a/gui/devices/320x320/res/images/file.png b/gui/devices/320x320/res/images/file.png
new file mode 100644
index 000000000..81ba38113
--- /dev/null
+++ b/gui/devices/320x320/res/images/file.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/folder.png b/gui/devices/320x320/res/images/folder.png
new file mode 100644
index 000000000..feeffe181
--- /dev/null
+++ b/gui/devices/320x320/res/images/folder.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/home-icon.png b/gui/devices/320x320/res/images/home-icon.png
new file mode 100644
index 000000000..444ffa509
--- /dev/null
+++ b/gui/devices/320x320/res/images/home-icon.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/indeterminate001.png b/gui/devices/320x320/res/images/indeterminate001.png
new file mode 100644
index 000000000..4a80bc5ac
--- /dev/null
+++ b/gui/devices/320x320/res/images/indeterminate001.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/indeterminate002.png b/gui/devices/320x320/res/images/indeterminate002.png
new file mode 100644
index 000000000..a0b1a03d5
--- /dev/null
+++ b/gui/devices/320x320/res/images/indeterminate002.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/indeterminate003.png b/gui/devices/320x320/res/images/indeterminate003.png
new file mode 100644
index 000000000..c59c24260
--- /dev/null
+++ b/gui/devices/320x320/res/images/indeterminate003.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/indeterminate004.png b/gui/devices/320x320/res/images/indeterminate004.png
new file mode 100644
index 000000000..0d7a3a49e
--- /dev/null
+++ b/gui/devices/320x320/res/images/indeterminate004.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/indeterminate005.png b/gui/devices/320x320/res/images/indeterminate005.png
new file mode 100644
index 000000000..a9a6638d9
--- /dev/null
+++ b/gui/devices/320x320/res/images/indeterminate005.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/indeterminate006.png b/gui/devices/320x320/res/images/indeterminate006.png
new file mode 100644
index 000000000..386abba25
--- /dev/null
+++ b/gui/devices/320x320/res/images/indeterminate006.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/keyboard1.png b/gui/devices/320x320/res/images/keyboard1.png
new file mode 100644
index 000000000..49e2d50b4
--- /dev/null
+++ b/gui/devices/320x320/res/images/keyboard1.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/keyboard2.png b/gui/devices/320x320/res/images/keyboard2.png
new file mode 100644
index 000000000..bf7668a6a
--- /dev/null
+++ b/gui/devices/320x320/res/images/keyboard2.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/keyboard3.png b/gui/devices/320x320/res/images/keyboard3.png
new file mode 100644
index 000000000..ff4d63e8b
--- /dev/null
+++ b/gui/devices/320x320/res/images/keyboard3.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/keyboard4.png b/gui/devices/320x320/res/images/keyboard4.png
new file mode 100644
index 000000000..5939b5231
--- /dev/null
+++ b/gui/devices/320x320/res/images/keyboard4.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/medium-button.png b/gui/devices/320x320/res/images/medium-button.png
new file mode 100644
index 000000000..379eb8616
--- /dev/null
+++ b/gui/devices/320x320/res/images/medium-button.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/menu-button.png b/gui/devices/320x320/res/images/menu-button.png
new file mode 100644
index 000000000..109a148e7
--- /dev/null
+++ b/gui/devices/320x320/res/images/menu-button.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/minus-button.png b/gui/devices/320x320/res/images/minus-button.png
new file mode 100644
index 000000000..2f1b27fff
--- /dev/null
+++ b/gui/devices/320x320/res/images/minus-button.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/plus-button.png b/gui/devices/320x320/res/images/plus-button.png
new file mode 100644
index 000000000..f223a98ac
--- /dev/null
+++ b/gui/devices/320x320/res/images/plus-button.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/progress_empty.png b/gui/devices/320x320/res/images/progress_empty.png
new file mode 100644
index 000000000..6d906d264
--- /dev/null
+++ b/gui/devices/320x320/res/images/progress_empty.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/progress_fill.png b/gui/devices/320x320/res/images/progress_fill.png
new file mode 100644
index 000000000..c4b590300
--- /dev/null
+++ b/gui/devices/320x320/res/images/progress_fill.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/radio_empty.png b/gui/devices/320x320/res/images/radio_empty.png
new file mode 100644
index 000000000..0766a307e
--- /dev/null
+++ b/gui/devices/320x320/res/images/radio_empty.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/radio_selected.png b/gui/devices/320x320/res/images/radio_selected.png
new file mode 100644
index 000000000..cf0d92539
--- /dev/null
+++ b/gui/devices/320x320/res/images/radio_selected.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/slideout.png b/gui/devices/320x320/res/images/slideout.png
new file mode 100644
index 000000000..df7a0fa70
--- /dev/null
+++ b/gui/devices/320x320/res/images/slideout.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/slider-touch.png b/gui/devices/320x320/res/images/slider-touch.png
new file mode 100644
index 000000000..e069c0fbb
--- /dev/null
+++ b/gui/devices/320x320/res/images/slider-touch.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/slider-used.png b/gui/devices/320x320/res/images/slider-used.png
new file mode 100644
index 000000000..bd37e5457
--- /dev/null
+++ b/gui/devices/320x320/res/images/slider-used.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/slider.png b/gui/devices/320x320/res/images/slider.png
new file mode 100644
index 000000000..d735417f1
--- /dev/null
+++ b/gui/devices/320x320/res/images/slider.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/sort-button.png b/gui/devices/320x320/res/images/sort-button.png
new file mode 100644
index 000000000..07b1b2498
--- /dev/null
+++ b/gui/devices/320x320/res/images/sort-button.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/twrplogo.png b/gui/devices/320x320/res/images/twrplogo.png
new file mode 100644
index 000000000..a95be1a30
--- /dev/null
+++ b/gui/devices/320x320/res/images/twrplogo.png
Binary files differ
diff --git a/gui/devices/320x320/res/images/unlock.png b/gui/devices/320x320/res/images/unlock.png
new file mode 100644
index 000000000..c6b5cffea
--- /dev/null
+++ b/gui/devices/320x320/res/images/unlock.png
Binary files differ
diff --git a/gui/devices/320x320/res/ui.xml b/gui/devices/320x320/res/ui.xml
new file mode 100644
index 000000000..1dec40504
--- /dev/null
+++ b/gui/devices/320x320/res/ui.xml
@@ -0,0 +1,434 @@
+<?xml version="1.0"?>
+
+<recovery>
+ <details>
+ <resolution width="320" height="320" />
+ <roundscreen offset_x="40" offset_y="40" />
+ <author>TeamWin</author>
+ <title>Backup Naowz</title>
+ <description>Default basic theme</description>
+ <preview>preview.jpg</preview>
+ </details>
+
+ <include>
+ <xmlfile name="watch.xml" />
+ </include>
+
+ <resources>
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-14" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-14" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="14" fallback="Roboto-Condensed-14" />
+ <resource name="fixed" type="font" filename="DroidSansMono.ttf" size="12" />
+ <resource name="twrplogo" type="image" filename="twrplogo" retainaspect="1" />
+ <resource name="main_button" type="image" filename="menu-button" />
+ <resource name="file_icon" type="image" filename="file" retainaspect="1" />
+ <resource name="folder_icon" type="image" filename="folder" retainaspect="1" />
+ <resource name="slideout" type="image" filename="slideout" retainaspect="1" />
+ <resource name="progress" type="animation" filename="indeterminate" />
+ <resource name="progress_empty" type="image" filename="progress_empty" />
+ <resource name="progress_full" type="image" filename="progress_fill" />
+ <resource name="checkbox_false" type="image" filename="checkbox_empty" retainaspect="1" />
+ <resource name="checkbox_true" type="image" filename="checkbox_checked" retainaspect="1" />
+ <resource name="radio_false" type="image" filename="radio_empty" retainaspect="1" />
+ <resource name="radio_true" type="image" filename="radio_selected" retainaspect="1" />
+ <resource name="medium_button" type="image" filename="medium-button" />
+ <resource name="sort_button" type="image" filename="sort-button" />
+ <resource name="minus_button" type="image" filename="minus-button" />
+ <resource name="plus_button" type="image" filename="plus-button" />
+ <resource name="home_icon" type="image" filename="home-icon" retainaspect="1" />
+ <resource name="back_icon" type="image" filename="back-icon" retainaspect="1" />
+ <resource name="slider" type="image" filename="slider" retainaspect="1" />
+ <resource name="slider-used" type="image" filename="slider-used" retainaspect="1" />
+ <resource name="slider-touch" type="image" filename="slider-touch" retainaspect="1" />
+ <resource name="unlock-icon" type="image" filename="unlock" retainaspect="1" />
+ <resource name="keyboard1" type="image" filename="keyboard1" />
+ <resource name="keyboard2" type="image" filename="keyboard2" />
+ <resource name="keyboard3" type="image" filename="keyboard3" />
+ <resource name="keyboard4" type="image" filename="keyboard4" />
+ <resource name="cursor" type="image" filename="cursor" retainaspect="1" />
+ </resources>
+
+ <variables>
+ <variable name="col1_x" value="6" />
+ <variable name="col2_x" value="170" />
+ <variable name="col_center_x" value="88" />
+ <variable name="col_center_medium_x" value="130" />
+ <variable name="center_x" value="160" />
+ <variable name="row1_home_y" value="50" />
+ <variable name="row2_home_y" value="110" />
+ <variable name="row3_home_y" value="170" />
+ <variable name="row4_home_y" value="230" />
+ <variable name="row1_y" value="30" />
+ <variable name="row2_y" value="100" />
+ <variable name="row3_y" value="170" />
+ <variable name="row4_y" value="240" />
+ <variable name="row_queue_y" value="184" />
+ <variable name="row1_header_y" value="0" />
+ <variable name="row1_text_y" value="22" />
+ <variable name="row2_text_y" value="44" />
+ <variable name="row3_text_y" value="66" />
+ <variable name="row4_text_y" value="88" />
+ <variable name="row5_text_y" value="110" />
+ <variable name="row6_text_y" value="132" />
+ <variable name="row7_text_y" value="154" />
+ <variable name="row8_text_y" value="176" />
+ <variable name="row9_text_y" value="198" />
+ <variable name="row10_text_y" value="220" />
+ <variable name="row11_text_y" value="242" />
+ <variable name="row12_text_y" value="284" />
+ <variable name="row13_text_y" value="306" />
+ <variable name="zip_status_y" value="300" />
+ <variable name="flash_list_height" value="160" />
+ <variable name="backup_text_y" value="60" />
+ <variable name="col_progressbar_x" value="34" />
+ <variable name="row_progressbar_y" value="285" />
+ <variable name="col1_medium_x" value="6" />
+ <variable name="col2_medium_x" value="83" />
+ <variable name="col3_medium_x" value="174" />
+ <variable name="col4_medium_x" value="254" />
+ <variable name="row1_medium_y" value="24" />
+ <variable name="row2_medium_y" value="40" />
+ <variable name="row3_medium_y" value="56" />
+ <variable name="row4_medium_y" value="72" />
+ <variable name="row5_medium_y" value="88" />
+ <variable name="row6_medium_y" value="104" />
+ <variable name="row7_medium_y" value="120" />
+ <variable name="slider_y" value="268" />
+ <variable name="slider_text_y" value="294" />
+ <variable name="button_text_color" value="#AAAAAA" />
+ <variable name="text_color" value="#FFFFFF" />
+ <variable name="text_success_color" value="#33B5E5" />
+ <variable name="text_fail_color" value="#FF0101" />
+ <variable name="highlight_color" value="#90909080" />
+ <variable name="caps_highlight_color" value="#33B5E580" />
+ <variable name="home_button_x" value="3" />
+ <variable name="home_button_y" value="300" />
+ <variable name="back_button_x" value="317" />
+ <variable name="back_button_y" value="300" />
+ <variable name="sort_text_x" value="20" />
+ <variable name="sort_asc_text_y" value="232" />
+ <variable name="sort_asc_button_y" value="230" />
+ <variable name="sort_desc_text_y" value="262" />
+ <variable name="sort_desc_button_y" value="260" />
+ <variable name="sort_col1_button_x" value="135" />
+ <variable name="sort_col2_button_x" value="195" />
+ <variable name="sort_col3_button_x" value="255" />
+ <variable name="input_width" value="308" />
+ <variable name="input_width_conf" value="10" />
+ <variable name="input_height" value="18" />
+ <variable name="input_background_color" value="#303030" />
+ <variable name="input_cursor_color" value="#33B5E5" />
+ <variable name="input_cursor_width" value="2" />
+ <variable name="console_x" value="0" />
+ <variable name="console_width" value="320" />
+ <variable name="console_foreground" value="#A0A0A0" />
+ <variable name="warning" value="#F8F8A0" />
+ <variable name="error" value="#FF4040" />
+ <variable name="highlight" value="#33B5E5" />
+ <variable name="console_background" value="#303030" />
+ <variable name="console_scroll" value="#303030" />
+ <variable name="console_action_height" value="160" />
+ <variable name="console_install_height" value="160" />
+ <variable name="console_installdone_height" value="160" />
+ <variable name="fileselector_x" value="0" />
+ <variable name="fileselector_y" value="44" />
+ <variable name="fileselector_width" value="320" />
+ <variable name="fileselector_install_height" value="182" />
+ <variable name="fileselector_header_background" value="#202020" />
+ <variable name="fileselector_header_textcolor" value="#AAAAAA" />
+ <variable name="fileselector_header_separatorcolor" value="#33B5E5" />
+ <variable name="fileselector_header_separatorheight" value="2" />
+ <variable name="fileselector_separatorcolor" value="#505050" />
+ <variable name="fileselector_separatorheight" value="1" />
+ <variable name="fileselector_background" value="#303030" />
+ <variable name="fileselector_highlight_color" value="#505050" />
+ <variable name="fileselector_highlight_font_color" value="#33B5E5" />
+ <variable name="fileselector_spacing" value="12" />
+ <variable name="fastscroll_linecolor" value="#50505080" />
+ <variable name="fastscroll_rectcolor" value="#33B5E580" />
+ <variable name="fastscroll_w" value="32" />
+ <variable name="fastscroll_linew" value="1" />
+ <variable name="fastscroll_rectw" value="7" />
+ <variable name="fastscroll_recth" value="24" />
+ <variable name="listbox_x" value="0" />
+ <variable name="listbox_width" value="320" />
+ <variable name="listbox_background" value="#303030" />
+ <variable name="listbox_spacing" value="12" />
+ <variable name="sd_plus_x" value="174" />
+ <variable name="sdext_text_x" value="56" />
+ <variable name="sdext_text_y" value="18" />
+ <variable name="sdswap_button_y" value="45" />
+ <variable name="sdswap_text_x" value="56" />
+ <variable name="sdswap_text_y" value="47" />
+ <variable name="sdfilesystem_text_y" value="92" />
+ <variable name="sdfilesystem_button_y" value="120" />
+ <variable name="lock_y" value="120" />
+ <variable name="filemanager_select_x" value="130" />
+ <variable name="filemanager_select_y" value="280" />
+ <variable name="terminal_console_height" value="126" />
+ <variable name="terminal_text_y" value="128" />
+ <variable name="terminal_button_y" value="300" />
+ <variable name="listbox_tz_height" value="159" />
+ <variable name="row_dst_text_y" value="162" />
+ <variable name="row_offset_text_y" value="184" />
+ <variable name="row_offset_medium_y" value="206" />
+ <variable name="tz_set_y" value="271" />
+ <variable name="tz_current_y" value="249" />
+ <variable name="system_ro_y" value="216" />
+ <variable name="button_fill_color" value="#303030" />
+ <variable name="button_fill_full_width" value="308" />
+ <variable name="button_fill_main_width" value="150" />
+ <variable name="button_fill_med_width" value="72" />
+ <variable name="button_fill_small_width" value="36" />
+ <variable name="button_fill_main_height" value="44" />
+ <variable name="button_fill_half_height" value="22" />
+ <variable name="button_fill_quarter_height" value="22" />
+ <variable name="button_refresh_x" value="152" />
+ <variable name="backup_list_y" value="26" />
+ <variable name="backup_list_height" value="184" />
+ <variable name="restore_list_height" value="206" />
+ <variable name="backup_button_row1" value="214" />
+ <variable name="backup_button_row2" value="242" />
+ <variable name="mount_list_height" value="190" />
+ <variable name="mount_storage_row" value="193" />
+ <variable name="storage_list_height" value="134" />
+ <variable name="wipe_list_height" value="216" />
+ <variable name="wipe_button_y" value="170" />
+ <variable name="slidervalue_w" value="308" />
+ <variable name="slidervalue_line_clr" value="#FFFFFF" />
+ <variable name="slidervalue_slider_clr" value="#33B5E5" />
+ <variable name="slidervalue_lineh" value="1" />
+ <variable name="slidervalue_padding" value="8" />
+ <variable name="slidervalue_sliderw" value="4" />
+ <variable name="slidervalue_sliderh" value="20" />
+ <variable name="wipe_button_row1" value="240" />
+ <variable name="invalid_partition_y" value="218" />
+ <variable name="pattern_x" value="70" />
+ <variable name="pattern_y" value="22" />
+ <variable name="pattern_width" value="180" />
+ <variable name="pattern_dot_color" value="#33B5E5" />
+ <variable name="pattern_dot_color_active" value="#FFFFFF" />
+ <variable name="pattern_dot_radius" value="7" />
+ <variable name="pattern_line_color" value="#33B5E5" />
+ <variable name="pattern_line_width" value="4" />
+ </variables>
+
+ <templates>
+ <template name="twrpheader">
+ <object type="fill" color="%button_fill_color%">
+ <placement x="0" y="0" w="320" h="26" />
+ </object>
+
+ <object type="fill" color="%highlight%">
+ <placement x="0" y="26" w="320" h="1" />
+ </object>
+
+ <object type="image">
+ <image resource="twrplogo" />
+ <placement x="13" y="13" placement="4" />
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="25" y="3" />
+ <text>TWRP v%tw_version%</text>
+ </object>
+
+ <object type="text" color="%text_fail_color%">
+ <condition var1="tw_simulate_actions" var2="1" />
+ <font resource="font" />
+ <placement x="25" y="21" />
+ <text>SIMULATION</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="160" y="3" placement="5" />
+ <text>%tw_time%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="316" y="3" placement="1" />
+ <conditions>
+ <condition var1="tw_no_battery_percent" var2="0" />
+ <condition var1="tw_battery" op="&gt;" var2="0" />
+ <condition var1="tw_battery" op="&lt;" var2="101" />
+ </conditions>
+ <text>%tw_battery%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="190" y="3" />
+ <conditions>
+ <condition var1="tw_no_cpu_temp" var2="0" />
+ </conditions>
+ <text>CPU: %tw_cpu_temp% C</text>
+ </object>
+ </template>
+
+ <template name="header">
+ <background color="#000000FF" />
+
+ <object type="button">
+ <placement x="%home_button_x%" y="%home_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="home_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">home</action>
+ </object>
+
+ <object type="button">
+ <placement x="%back_button_x%" y="%back_button_y%" placement="1" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="back_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">back</action>
+ </object>
+
+ <object type="action">
+ <touch key="power" />
+ <action function="key">back</action>
+ </object>
+
+ <object type="action">
+ <touch key="power+voldown" />
+ <action function="screenshot" />
+ </object>
+ </template>
+
+ <template name="progress_bar">
+ <object type="progressbar">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource empty="progress_empty" full="progress_full" />
+ <data name="ui_progress" />
+ </object>
+
+ <object type="animation">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource name="progress" />
+ <speed fps="15" render="2" />
+ <loop frame="1" />
+ </object>
+ </template>
+
+ <template name="action_page_console">
+ <object type="console">
+ <placement x="%console_x%" y="%row2_y%" w="%console_width%" h="%console_action_height%" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="sort_options">
+ <object type="text" color="%text_color%">
+ <font resource="mediumfont" />
+ <placement x="%sort_text_x%" y="%sort_asc_text_y%" />
+ <text>Sort Ascending:</text>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col1_button_x%" y="%sort_asc_button_y%" />
+ <font resource="mediumfont" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col2_button_x%" y="%sort_asc_button_y%" />
+ <font resource="mediumfont" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=2</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col3_button_x%" y="%sort_asc_button_y%" />
+ <font resource="mediumfont" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=3</action>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="mediumfont" />
+ <placement x="%sort_text_x%" y="%sort_desc_text_y%" />
+ <text>Sort Descending:</text>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col1_button_x%" y="%sort_desc_button_y%" />
+ <font resource="mediumfont" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col2_button_x%" y="%sort_desc_button_y%" />
+ <font resource="mediumfont" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-2</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col3_button_x%" y="%sort_desc_button_y%" />
+ <font resource="mediumfont" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-3</action>
+ </object>
+ </template>
+
+ <template name="footer">
+ <object type="console">
+ <slideout resource="slideout" x="%center_x%" y="288" placement="5" />
+ <placement x="%console_x%" y="0" w="%console_width%" h="288" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="keyboardtemplate">
+ <object type="keyboard">
+ <placement x="0" y="150" />
+ <layout resource1="keyboard1" resource2="keyboard2" resource3="keyboard3" resource4="keyboard4" />
+ <highlight color="%highlight_color%" />
+ <capshighlight color="%caps_highlight_color%" />
+ <layout1>
+ <keysize height="36" width="32" />
+ <row1 key01="q" long01="1" key02="w" long02="2" key03="e" long03="3" key04="r" long04="4" key05="t" long05="5" key06="y" long06="6" key07="u" long07="7" key08="i" long08="8" key09="o" long09="9" key10="p" long10="0" />
+ <row2 key01="48:a" key02="s" key03="d" key04="f" key05="g" key06="h" key07="j" key08="k" key09="48:l" />
+ <row3 key01="48:layout2" key02="z" key03="x" key04="c" key05="v" key06="b" key07="n" key08="m" key09="48:c:8" />
+ <row4 key01="48:layout3" key02="32:," key03="160: " key04="32:." key05="48:a:action" />
+ </layout1>
+ <layout2>
+ <keysize height="36" width="32" capslock="0" revert_layout="1" />
+ <row1 key01="Q" long01="1" key02="W" long02="2" key03="E" long03="3" key04="R" long04="4" key05="T" long05="5" key06="Y" long06="6" key07="U" long07="7" key08="I" long08="8" key09="O" long09="9" key10="P" long10="0" />
+ <row2 key01="48:A" key02="S" key03="D" key04="F" key05="G" key06="H" key07="J" key08="K" key09="48:L" />
+ <row3 key01="48:layout1" key02="Z" key03="X" key04="C" key05="V" key06="B" key07="N" key08="M" key09="48:c:8" />
+ <row4 key01="48:layout3" key02="32:," key03="160: " key04="32:." key05="48:action" />
+ </layout2>
+ <layout3>
+ <keysize height="36" width="32" />
+ <row1 key01="1" key02="2" key03="3" key04="4" key05="5" key06="6" key07="7" key08="8" key09="9" key10="0" />
+ <row2 key01="@" key02="#" key03="$" key04="%" key05="&amp;" key06="*" key07="-" key08="+" key09="(" key10=")" />
+ <row3 key01="48:layout4" key02="!" key03="32:c:34" key04="'" key05=":" key06=";" key07="/" key08="?" key09="48:c:8" />
+ <row4 key01="48:layout1" key02="32:," key03="160: " key04="32:." key05="48:action" />
+ </layout3>
+ <layout4>
+ <keysize height="36" width="32" />
+ <row1 key01="~" key02="`" key03="|" key04="32:" key05="32:" key06="32:" key07="%" key08="32:" key09="{" key10="}" />
+ <row2 key01="32:" key02="32:" key03="32:" key04="32:" key05="32:" key06="^" key07="_" key08="=" key09="[" key10="]" />
+ <row3 key01="48:layout3" key02="32:" key03="32:" key04="32:" key05="32:" key06="\" key07="&lt;" key08="&gt;" key09="48:c:8" />
+ <row4 key01="48:layout1" key02="32:c:34" key03="160: " key04="32:." key05="48:action" />
+ </layout4>
+ </object>
+ </template>
+ </templates>
+</recovery>
diff --git a/gui/devices/480x800/res/fonts/Roboto-Regular-20.dat b/gui/devices/480x800/res/fonts/Roboto-Regular-20.dat
new file mode 100644
index 000000000..6588b41e7
--- /dev/null
+++ b/gui/devices/480x800/res/fonts/Roboto-Regular-20.dat
Binary files differ
diff --git a/gui/devices/480x800/res/images/back-icon.png b/gui/devices/480x800/res/images/back-icon.png
new file mode 100644
index 000000000..688436eb2
--- /dev/null
+++ b/gui/devices/480x800/res/images/back-icon.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/checkbox_checked.png b/gui/devices/480x800/res/images/checkbox_checked.png
new file mode 100644
index 000000000..3447349cf
--- /dev/null
+++ b/gui/devices/480x800/res/images/checkbox_checked.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/checkbox_empty.png b/gui/devices/480x800/res/images/checkbox_empty.png
new file mode 100644
index 000000000..f5f35d8d1
--- /dev/null
+++ b/gui/devices/480x800/res/images/checkbox_empty.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/cursor.png b/gui/devices/480x800/res/images/cursor.png
new file mode 100644
index 000000000..32c8ae1ca
--- /dev/null
+++ b/gui/devices/480x800/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/curtain.jpg b/gui/devices/480x800/res/images/curtain.jpg
new file mode 100644
index 000000000..dfd59d96b
--- /dev/null
+++ b/gui/devices/480x800/res/images/curtain.jpg
Binary files differ
diff --git a/gui/devices/480x800/res/images/file.png b/gui/devices/480x800/res/images/file.png
new file mode 100644
index 000000000..8556bc7fa
--- /dev/null
+++ b/gui/devices/480x800/res/images/file.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/folder.png b/gui/devices/480x800/res/images/folder.png
new file mode 100644
index 000000000..a3a5f69df
--- /dev/null
+++ b/gui/devices/480x800/res/images/folder.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/home-icon.png b/gui/devices/480x800/res/images/home-icon.png
new file mode 100644
index 000000000..551952015
--- /dev/null
+++ b/gui/devices/480x800/res/images/home-icon.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/indeterminate001.png b/gui/devices/480x800/res/images/indeterminate001.png
new file mode 100644
index 000000000..e6fa1c574
--- /dev/null
+++ b/gui/devices/480x800/res/images/indeterminate001.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/indeterminate002.png b/gui/devices/480x800/res/images/indeterminate002.png
new file mode 100644
index 000000000..e1fceaba1
--- /dev/null
+++ b/gui/devices/480x800/res/images/indeterminate002.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/indeterminate003.png b/gui/devices/480x800/res/images/indeterminate003.png
new file mode 100644
index 000000000..670286743
--- /dev/null
+++ b/gui/devices/480x800/res/images/indeterminate003.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/indeterminate004.png b/gui/devices/480x800/res/images/indeterminate004.png
new file mode 100644
index 000000000..ff65e0930
--- /dev/null
+++ b/gui/devices/480x800/res/images/indeterminate004.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/indeterminate005.png b/gui/devices/480x800/res/images/indeterminate005.png
new file mode 100644
index 000000000..e61e2cc15
--- /dev/null
+++ b/gui/devices/480x800/res/images/indeterminate005.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/indeterminate006.png b/gui/devices/480x800/res/images/indeterminate006.png
new file mode 100644
index 000000000..c9c21ba9c
--- /dev/null
+++ b/gui/devices/480x800/res/images/indeterminate006.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/keyboard1.png b/gui/devices/480x800/res/images/keyboard1.png
new file mode 100644
index 000000000..5a691ac02
--- /dev/null
+++ b/gui/devices/480x800/res/images/keyboard1.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/keyboard2.png b/gui/devices/480x800/res/images/keyboard2.png
new file mode 100644
index 000000000..69b015458
--- /dev/null
+++ b/gui/devices/480x800/res/images/keyboard2.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/keyboard3.png b/gui/devices/480x800/res/images/keyboard3.png
new file mode 100644
index 000000000..498cef84b
--- /dev/null
+++ b/gui/devices/480x800/res/images/keyboard3.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/keyboard4.png b/gui/devices/480x800/res/images/keyboard4.png
new file mode 100644
index 000000000..e8f9dde0e
--- /dev/null
+++ b/gui/devices/480x800/res/images/keyboard4.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/medium-button.png b/gui/devices/480x800/res/images/medium-button.png
new file mode 100644
index 000000000..1d5b816ec
--- /dev/null
+++ b/gui/devices/480x800/res/images/medium-button.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/menu-button.png b/gui/devices/480x800/res/images/menu-button.png
new file mode 100644
index 000000000..c8d3794e5
--- /dev/null
+++ b/gui/devices/480x800/res/images/menu-button.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/minus-button.png b/gui/devices/480x800/res/images/minus-button.png
new file mode 100644
index 000000000..9c92d2f46
--- /dev/null
+++ b/gui/devices/480x800/res/images/minus-button.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/plus-button.png b/gui/devices/480x800/res/images/plus-button.png
new file mode 100644
index 000000000..5d3068ed9
--- /dev/null
+++ b/gui/devices/480x800/res/images/plus-button.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/progress_empty.png b/gui/devices/480x800/res/images/progress_empty.png
new file mode 100644
index 000000000..b85371014
--- /dev/null
+++ b/gui/devices/480x800/res/images/progress_empty.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/progress_fill.png b/gui/devices/480x800/res/images/progress_fill.png
new file mode 100644
index 000000000..669c6efa9
--- /dev/null
+++ b/gui/devices/480x800/res/images/progress_fill.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/radio_empty.png b/gui/devices/480x800/res/images/radio_empty.png
new file mode 100644
index 000000000..88d1c1f5e
--- /dev/null
+++ b/gui/devices/480x800/res/images/radio_empty.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/radio_selected.png b/gui/devices/480x800/res/images/radio_selected.png
new file mode 100644
index 000000000..864065dea
--- /dev/null
+++ b/gui/devices/480x800/res/images/radio_selected.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/slideout.png b/gui/devices/480x800/res/images/slideout.png
new file mode 100644
index 000000000..963b9fdba
--- /dev/null
+++ b/gui/devices/480x800/res/images/slideout.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/slider-touch.png b/gui/devices/480x800/res/images/slider-touch.png
new file mode 100644
index 000000000..c8c0f43c3
--- /dev/null
+++ b/gui/devices/480x800/res/images/slider-touch.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/slider-used.png b/gui/devices/480x800/res/images/slider-used.png
new file mode 100644
index 000000000..2f3d51969
--- /dev/null
+++ b/gui/devices/480x800/res/images/slider-used.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/slider.png b/gui/devices/480x800/res/images/slider.png
new file mode 100644
index 000000000..6fcce6f5b
--- /dev/null
+++ b/gui/devices/480x800/res/images/slider.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/sort-button.png b/gui/devices/480x800/res/images/sort-button.png
new file mode 100644
index 000000000..69d511bea
--- /dev/null
+++ b/gui/devices/480x800/res/images/sort-button.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/twrplogo.png b/gui/devices/480x800/res/images/twrplogo.png
new file mode 100644
index 000000000..4b39da89b
--- /dev/null
+++ b/gui/devices/480x800/res/images/twrplogo.png
Binary files differ
diff --git a/gui/devices/480x800/res/images/unlock.png b/gui/devices/480x800/res/images/unlock.png
new file mode 100644
index 000000000..904122120
--- /dev/null
+++ b/gui/devices/480x800/res/images/unlock.png
Binary files differ
diff --git a/gui/devices/480x800/res/ui.xml b/gui/devices/480x800/res/ui.xml
new file mode 100644
index 000000000..341332f83
--- /dev/null
+++ b/gui/devices/480x800/res/ui.xml
@@ -0,0 +1,430 @@
+<?xml version="1.0"?>
+
+<recovery>
+ <details>
+ <resolution width="480" height="800" />
+ <author>TeamWin</author>
+ <title>Backup Naowz</title>
+ <description>Default basic theme</description>
+ <preview>preview.jpg</preview>
+ </details>
+
+ <include>
+ <xmlfile name="portrait.xml" />
+ </include>
+
+ <resources>
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="mediumfont" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="filelist" type="font" filename="RobotoCondensed-Regular.ttf" size="20" fallback="Roboto-Regular-20" />
+ <resource name="fixed" type="font" filename="DroidSansMono.ttf" size="16" />
+ <resource name="twrplogo" type="image" filename="twrplogo" retainaspect="1" />
+ <resource name="main_button" type="image" filename="menu-button" />
+ <resource name="file_icon" type="image" filename="file" retainaspect="1" />
+ <resource name="folder_icon" type="image" filename="folder" retainaspect="1" />
+ <resource name="slideout" type="image" filename="slideout" retainaspect="1" />
+ <resource name="progress" type="animation" filename="indeterminate" />
+ <resource name="progress_empty" type="image" filename="progress_empty" />
+ <resource name="progress_full" type="image" filename="progress_fill" />
+ <resource name="checkbox_false" type="image" filename="checkbox_empty" retainaspect="1" />
+ <resource name="checkbox_true" type="image" filename="checkbox_checked" retainaspect="1" />
+ <resource name="radio_false" type="image" filename="radio_empty" retainaspect="1" />
+ <resource name="radio_true" type="image" filename="radio_selected" retainaspect="1" />
+ <resource name="medium_button" type="image" filename="medium-button" />
+ <resource name="sort_button" type="image" filename="sort-button" />
+ <resource name="minus_button" type="image" filename="minus-button" />
+ <resource name="plus_button" type="image" filename="plus-button" />
+ <resource name="home_icon" type="image" filename="home-icon" retainaspect="1" />
+ <resource name="back_icon" type="image" filename="back-icon" retainaspect="1" />
+ <resource name="slider" type="image" filename="slider" retainaspect="1" />
+ <resource name="slider-used" type="image" filename="slider-used" retainaspect="1" />
+ <resource name="slider-touch" type="image" filename="slider-touch" retainaspect="1" />
+ <resource name="unlock-icon" type="image" filename="unlock" retainaspect="1" />
+ <resource name="keyboard1" type="image" filename="keyboard1" />
+ <resource name="keyboard2" type="image" filename="keyboard2" />
+ <resource name="keyboard3" type="image" filename="keyboard3" />
+ <resource name="keyboard4" type="image" filename="keyboard4" />
+ <resource name="cursor" type="image" filename="cursor" retainaspect="1" />
+ </resources>
+
+ <variables>
+ <variable name="col1_x" value="10" />
+ <variable name="col2_x" value="240" />
+ <variable name="col_center_x" value="128" />
+ <variable name="col_center_medium_x" value="183" />
+ <variable name="center_x" value="240" />
+ <variable name="row1_y" value="140" />
+ <variable name="row2_y" value="290" />
+ <variable name="row3_y" value="450" />
+ <variable name="row4_y" value="610" />
+ <variable name="row_queue_y" value="510" />
+ <variable name="row1_header_y" value="110" />
+ <variable name="row1_text_y" value="140" />
+ <variable name="row2_text_y" value="170" />
+ <variable name="row3_text_y" value="200" />
+ <variable name="row4_text_y" value="230" />
+ <variable name="row5_text_y" value="260" />
+ <variable name="row6_text_y" value="290" />
+ <variable name="row7_text_y" value="320" />
+ <variable name="row8_text_y" value="350" />
+ <variable name="row9_text_y" value="380" />
+ <variable name="row10_text_y" value="410" />
+ <variable name="row11_text_y" value="440" />
+ <variable name="row12_text_y" value="470" />
+ <variable name="row13_text_y" value="500" />
+ <variable name="row14_text_y" value="530" />
+ <variable name="row15_text_y" value="560" />
+ <variable name="row16_text_y" value="590" />
+ <variable name="row17_text_y" value="620" />
+ <variable name="row18_text_y" value="650" />
+ <variable name="zip_status_y" value="585" />
+ <variable name="flash_list_height" value="210" />
+ <variable name="tz_selected_y" value="110" />
+ <variable name="tz_set_y" value="580" />
+ <variable name="tz_current_y" value="730" />
+ <variable name="system_ro_y" value="550" />
+ <variable name="col_progressbar_x" value="114" />
+ <variable name="row_progressbar_y" value="720" />
+ <variable name="col1_medium_x" value="10" />
+ <variable name="col2_medium_x" value="125" />
+ <variable name="col3_medium_x" value="240" />
+ <variable name="col4_medium_x" value="355" />
+ <variable name="row1_medium_y" value="130" />
+ <variable name="row2_medium_y" value="205" />
+ <variable name="row3_medium_y" value="280" />
+ <variable name="row4_medium_y" value="355" />
+ <variable name="row5_medium_y" value="430" />
+ <variable name="row6_medium_y" value="505" />
+ <variable name="row7_medium_y" value="580" />
+ <variable name="slider_y" value="680" />
+ <variable name="slider_text_y" value="721" />
+ <variable name="button_text_color" value="#AAAAAA" />
+ <variable name="text_color" value="#FFFFFF" />
+ <variable name="text_success_color" value="#33B5E5" />
+ <variable name="text_fail_color" value="#FF0101" />
+ <variable name="highlight_color" value="#90909080" />
+ <variable name="caps_highlight_color" value="#33B5E580" />
+ <variable name="home_button_x" value="10" />
+ <variable name="home_button_y" value="766" />
+ <variable name="back_button_x" value="470" />
+ <variable name="back_button_y" value="766" />
+ <variable name="sort_asc_text_y" value="685" />
+ <variable name="sort_asc_button_y" value="685" />
+ <variable name="sort_desc_text_y" value="725" />
+ <variable name="sort_desc_button_y" value="725" />
+ <variable name="sort_col1_button_x" value="180" />
+ <variable name="sort_col2_button_x" value="240" />
+ <variable name="sort_col3_button_x" value="300" />
+ <variable name="input_width" value="460" />
+ <variable name="input_height" value="40" />
+ <variable name="input_background_color" value="#303030" />
+ <variable name="input_cursor_color" value="#33B5E5" />
+ <variable name="input_cursor_width" value="3" />
+ <variable name="console_x" value="0" />
+ <variable name="console_width" value="480" />
+ <variable name="console_foreground" value="#A0A0A0" />
+ <variable name="warning" value="#F8F8A0" />
+ <variable name="error" value="#FF4040" />
+ <variable name="highlight" value="#33B5E5" />
+ <variable name="console_background" value="#303030" />
+ <variable name="console_scroll" value="#303030" />
+ <variable name="console_action_height" value="320" />
+ <variable name="console_install_height" value="440" />
+ <variable name="console_installdone_height" value="300" />
+ <variable name="fileselector_x" value="5" />
+ <variable name="fileselector_width" value="470" />
+ <variable name="fileselector_install_height" value="480" />
+ <variable name="fileselector_header_background" value="#202020" />
+ <variable name="fileselector_header_textcolor" value="#AAAAAA" />
+ <variable name="fileselector_header_separatorcolor" value="#33B5E5" />
+ <variable name="fileselector_header_separatorheight" value="3" />
+ <variable name="fileselector_separatorcolor" value="#505050" />
+ <variable name="fileselector_separatorheight" value="2" />
+ <variable name="fileselector_background" value="#303030" />
+ <variable name="fileselector_highlight_color" value="#505050" />
+ <variable name="fileselector_highlight_font_color" value="#33B5E5" />
+ <variable name="fileselector_spacing" value="18" />
+ <variable name="fastscroll_linecolor" value="#50505080" />
+ <variable name="fastscroll_rectcolor" value="#33B5E580" />
+ <variable name="fastscroll_w" value="40" />
+ <variable name="fastscroll_linew" value="2" />
+ <variable name="fastscroll_rectw" value="10" />
+ <variable name="fastscroll_recth" value="30" />
+ <variable name="listbox_x" value="5" />
+ <variable name="listbox_width" value="470" />
+ <variable name="listbox_tz_height" value="310" />
+ <variable name="listbox_background" value="#303030" />
+ <variable name="listbox_spacing" value="18" />
+ <variable name="sd_plus_x" value="280" />
+ <variable name="sdext_text_x" value="84" />
+ <variable name="sdext_text_y" value="145" />
+ <variable name="sdswap_button_y" value="185" />
+ <variable name="sdswap_text_x" value="84" />
+ <variable name="sdswap_text_y" value="190" />
+ <variable name="sdfilesystem_text_y" value="240" />
+ <variable name="sdfilesystem_button_y" value="280" />
+ <variable name="lock_y" value="250" />
+ <variable name="filemanager_select_x" value="365" />
+ <variable name="filemanager_select_y" value="690" />
+ <variable name="backup_name_y" value="350" />
+ <variable name="terminal_console_height" value="370" />
+ <variable name="terminal_text_y" value="390" />
+ <variable name="terminal_button_y" value="380" />
+ <variable name="row_dst_text_y" value="440" />
+ <variable name="row_offset_text_y" value="480" />
+ <variable name="row_offset_medium_y" value="505" />
+ <variable name="button_fill_color" value="#303030" />
+ <variable name="button_fill_full_width" value="455" />
+ <variable name="button_fill_main_width" value="225" />
+ <variable name="button_fill_main_height" value="135" />
+ <variable name="button_fill_half_height" value="67" />
+ <variable name="button_fill_quarter_height" value="34" />
+ <variable name="backup_list_height" value="300" />
+ <variable name="backup_button_row1" value="480" />
+ <variable name="backup_button_row2" value="520" />
+ <variable name="mount_list_height" value="380" />
+ <variable name="mount_storage_row" value="500" />
+ <variable name="storage_list_height" value="400" />
+ <variable name="wipe_list_height" value="460" />
+ <variable name="wipe_button_row1" value="600" />
+ <variable name="wipe_button_y" value="400" />
+ <variable name="slidervalue_w" value="460" />
+ <variable name="slidervalue_line_clr" value="#FFFFFF" />
+ <variable name="slidervalue_slider_clr" value="#33B5E5" />
+ <variable name="slidervalue_lineh" value="1" />
+ <variable name="slidervalue_padding" value="13" />
+ <variable name="slidervalue_sliderw" value="7" />
+ <variable name="slidervalue_sliderh" value="40" />
+ <variable name="pattern_x" value="90" />
+ <variable name="pattern_y" value="250" />
+ <variable name="pattern_width" value="300" />
+ <variable name="pattern_dot_color" value="#33B5E5" />
+ <variable name="pattern_dot_color_active" value="#FFFFFF" />
+ <variable name="pattern_dot_radius" value="12" />
+ <variable name="pattern_line_color" value="#33B5E5" />
+ <variable name="pattern_line_width" value="9" />
+ </variables>
+
+ <mousecursor>
+ <placement w="15" h="15" />
+ <background color="#FFFF00FF" resource="cursor" />
+ <speed multiplier="1.5" />
+ </mousecursor>
+
+ <templates>
+ <template name="header">
+ <background color="#000000FF" />
+
+ <object type="fill" color="%button_fill_color%">
+ <placement x="0" y="0" w="480" h="98" />
+ </object>
+
+ <object type="fill" color="%highlight%">
+ <placement x="0" y="98" w="480" h="2" />
+ </object>
+
+ <object type="image">
+ <image resource="twrplogo" />
+ <placement x="50" y="50" placement="4" />
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="100" y="10" />
+ <text>Team Win Recovery Project v%tw_version%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <condition var1="tw_simulate_actions" var2="1" />
+ <font resource="font" />
+ <placement x="100" y="40" />
+ <text>SIMULATING ACTIONS</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="100" y="70" />
+ <text>%tw_time%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="190" y="70" />
+ <conditions>
+ <condition var1="tw_no_battery_percent" var2="0" />
+ <condition var1="tw_battery" op="&gt;" var2="0" />
+ <condition var1="tw_battery" op="&lt;" var2="101" />
+ </conditions>
+ <text>Battery: %tw_battery%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="350" y="70" />
+ <conditions>
+ <condition var1="tw_no_cpu_temp" var2="0" />
+ </conditions>
+ <text>CPU: %tw_cpu_temp% C</text>
+ </object>
+
+ <object type="button">
+ <placement x="%home_button_x%" y="%home_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="home_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">home</action>
+ </object>
+
+ <object type="button">
+ <placement x="%back_button_x%" y="%back_button_y%" placement="1" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="back_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">back</action>
+ </object>
+
+ <object type="action">
+ <touch key="power" />
+ <action function="overlay">lock</action>
+ </object>
+
+ <object type="action">
+ <touch key="power+voldown" />
+ <action function="screenshot" />
+ </object>
+ </template>
+
+ <template name="progress_bar">
+ <object type="progressbar">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource empty="progress_empty" full="progress_full" />
+ <data name="ui_progress" />
+ </object>
+
+ <object type="animation">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource name="progress" />
+ <speed fps="15" render="2" />
+ <loop frame="1" />
+ </object>
+ </template>
+
+ <template name="action_page_console">
+ <object type="console">
+ <placement x="%console_x%" y="%row2_y%" w="%console_width%" h="%console_action_height%" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="sort_options">
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="%col1_x%" y="%sort_asc_text_y%" />
+ <text>Sort Ascending:</text>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col1_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col2_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=2</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col3_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=3</action>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="%col1_x%" y="%sort_desc_text_y%" />
+ <text>Sort Descending:</text>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col1_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col2_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-2</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sort_col3_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-3</action>
+ </object>
+ </template>
+
+ <template name="footer">
+ <object type="console">
+ <slideout resource="slideout" x="%center_x%" y="760" placement="5" />
+ <placement x="%console_x%" y="0" w="%console_width%" h="760" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="keyboardtemplate">
+ <object type="keyboard">
+ <placement x="0" y="450" />
+ <layout resource1="keyboard1" resource2="keyboard2" resource3="keyboard3" resource4="keyboard4" />
+ <highlight color="%highlight_color%" />
+ <capshighlight color="%caps_highlight_color%" />
+ <layout1>
+ <keysize height="78" width="48" />
+ <row1 key01="q" long01="1" key02="w" long02="2" key03="e" long03="3" key04="r" long04="4" key05="t" long05="5" key06="y" long06="6" key07="u" long07="7" key08="i" long08="8" key09="o" long09="9" key10="p" long10="0" />
+ <row2 key01="72:a" key02="s" key03="d" key04="f" key05="g" key06="h" key07="j" key08="k" key09="72:l" />
+ <row3 key01="72:layout2" key02="z" key03="x" key04="c" key05="v" key06="b" key07="n" key08="m" key09="72:c:8" />
+ <row4 key01="72:layout3" key02="48:" key03="240: " key04="48:." key05="72:a:action" />
+ </layout1>
+ <layout2>
+ <keysize height="78" width="48" capslock="0" revert_layout="1" />
+ <row1 key01="Q" long01="1" key02="W" long02="2" key03="E" long03="3" key04="R" long04="4" key05="T" long05="5" key06="Y" long06="6" key07="U" long07="7" key08="I" long08="8" key09="O" long09="9" key10="P" long10="0" />
+ <row2 key01="72:A" key02="S" key03="D" key04="F" key05="G" key06="H" key07="J" key08="K" key09="72:L" />
+ <row3 key01="72:layout1" key02="Z" key03="X" key04="C" key05="V" key06="B" key07="N" key08="M" key09="72:c:8" />
+ <row4 key01="72:layout3" key02="48:" key03="240: " key04="48:." key05="72:action" />
+ </layout2>
+ <layout3>
+ <keysize height="78" width="48" />
+ <row1 key01="1" key02="2" key03="3" key04="4" key05="5" key06="6" key07="7" key08="8" key09="9" key10="0" />
+ <row2 key01="@" key02="#" key03="$" key04="%" key05="&amp;" key06="*" key07="-" key08="+" key09="(" key10=")" />
+ <row3 key01="72:layout4" key02="!" key03="48:c:34" key04="'" key05=":" key06=";" key07="/" key08="?" key09="72:c:8" />
+ <row4 key01="72:layout1" key02="48:," key03="240: " key04="48:." key05="72:action" />
+ </layout3>
+ <layout4>
+ <keysize height="78" width="48" />
+ <row1 key01="~" key02="`" key03="|" key04="48:" key05="48:" key06="48:" key07="%" key08="48:" key09="{" key10="}" />
+ <row2 key01="48:" key02="48:" key03="48:" key04="48:" key05="48:" key06="^" key07="_" key08="=" key09="[" key10="]" />
+ <row3 key01="72:layout3" key02="48:" key03="48:" key04="48:" key05="48:" key06="\" key07="&lt;" key08="&gt;" key09="72:c:8" />
+ <row4 key01="72:layout1" key02="48:c:34" key03="240: " key04="48:." key05="72:action" />
+ </layout4>
+ </object>
+ </template>
+ </templates>
+</recovery>
diff --git a/gui/devices/800x480/res/fonts/Roboto-Condensed-16.dat b/gui/devices/800x480/res/fonts/Roboto-Condensed-16.dat
new file mode 100644
index 000000000..19c11470d
--- /dev/null
+++ b/gui/devices/800x480/res/fonts/Roboto-Condensed-16.dat
Binary files differ
diff --git a/gui/devices/800x480/res/images/back-icon.png b/gui/devices/800x480/res/images/back-icon.png
new file mode 100644
index 000000000..1096c9090
--- /dev/null
+++ b/gui/devices/800x480/res/images/back-icon.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/button.png b/gui/devices/800x480/res/images/button.png
new file mode 100644
index 000000000..49b878498
--- /dev/null
+++ b/gui/devices/800x480/res/images/button.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/checkbox_checked.png b/gui/devices/800x480/res/images/checkbox_checked.png
new file mode 100644
index 000000000..3759b7fd9
--- /dev/null
+++ b/gui/devices/800x480/res/images/checkbox_checked.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/checkbox_empty.png b/gui/devices/800x480/res/images/checkbox_empty.png
new file mode 100644
index 000000000..43a640427
--- /dev/null
+++ b/gui/devices/800x480/res/images/checkbox_empty.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/console-icon.png b/gui/devices/800x480/res/images/console-icon.png
new file mode 100644
index 000000000..91a727d40
--- /dev/null
+++ b/gui/devices/800x480/res/images/console-icon.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/console-toggle.png b/gui/devices/800x480/res/images/console-toggle.png
new file mode 100644
index 000000000..963b9fdba
--- /dev/null
+++ b/gui/devices/800x480/res/images/console-toggle.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/cursor.png b/gui/devices/800x480/res/images/cursor.png
new file mode 100644
index 000000000..32c8ae1ca
--- /dev/null
+++ b/gui/devices/800x480/res/images/cursor.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/curtain.jpg b/gui/devices/800x480/res/images/curtain.jpg
new file mode 100644
index 000000000..1f03eb5e5
--- /dev/null
+++ b/gui/devices/800x480/res/images/curtain.jpg
Binary files differ
diff --git a/gui/devices/800x480/res/images/file.png b/gui/devices/800x480/res/images/file.png
new file mode 100644
index 000000000..8556bc7fa
--- /dev/null
+++ b/gui/devices/800x480/res/images/file.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/folder.png b/gui/devices/800x480/res/images/folder.png
new file mode 100644
index 000000000..a3a5f69df
--- /dev/null
+++ b/gui/devices/800x480/res/images/folder.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/home-icon.png b/gui/devices/800x480/res/images/home-icon.png
new file mode 100644
index 000000000..e42d774b1
--- /dev/null
+++ b/gui/devices/800x480/res/images/home-icon.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/indeterminate001.png b/gui/devices/800x480/res/images/indeterminate001.png
new file mode 100755
index 000000000..e6fa1c574
--- /dev/null
+++ b/gui/devices/800x480/res/images/indeterminate001.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/indeterminate002.png b/gui/devices/800x480/res/images/indeterminate002.png
new file mode 100755
index 000000000..e1fceaba1
--- /dev/null
+++ b/gui/devices/800x480/res/images/indeterminate002.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/indeterminate003.png b/gui/devices/800x480/res/images/indeterminate003.png
new file mode 100755
index 000000000..670286743
--- /dev/null
+++ b/gui/devices/800x480/res/images/indeterminate003.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/indeterminate004.png b/gui/devices/800x480/res/images/indeterminate004.png
new file mode 100755
index 000000000..ff65e0930
--- /dev/null
+++ b/gui/devices/800x480/res/images/indeterminate004.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/indeterminate005.png b/gui/devices/800x480/res/images/indeterminate005.png
new file mode 100755
index 000000000..e61e2cc15
--- /dev/null
+++ b/gui/devices/800x480/res/images/indeterminate005.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/indeterminate006.png b/gui/devices/800x480/res/images/indeterminate006.png
new file mode 100755
index 000000000..c9c21ba9c
--- /dev/null
+++ b/gui/devices/800x480/res/images/indeterminate006.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/keyboard1.png b/gui/devices/800x480/res/images/keyboard1.png
new file mode 100644
index 000000000..1ccb64bb4
--- /dev/null
+++ b/gui/devices/800x480/res/images/keyboard1.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/keyboard2.png b/gui/devices/800x480/res/images/keyboard2.png
new file mode 100644
index 000000000..f19eaccab
--- /dev/null
+++ b/gui/devices/800x480/res/images/keyboard2.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/keyboard3.png b/gui/devices/800x480/res/images/keyboard3.png
new file mode 100644
index 000000000..022086064
--- /dev/null
+++ b/gui/devices/800x480/res/images/keyboard3.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/keyboard4.png b/gui/devices/800x480/res/images/keyboard4.png
new file mode 100644
index 000000000..7fc0ea50f
--- /dev/null
+++ b/gui/devices/800x480/res/images/keyboard4.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/medium-button.png b/gui/devices/800x480/res/images/medium-button.png
new file mode 100644
index 000000000..77dc54072
--- /dev/null
+++ b/gui/devices/800x480/res/images/medium-button.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/mediumwide-button.png b/gui/devices/800x480/res/images/mediumwide-button.png
new file mode 100644
index 000000000..b2b7d4de9
--- /dev/null
+++ b/gui/devices/800x480/res/images/mediumwide-button.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/minus-button.png b/gui/devices/800x480/res/images/minus-button.png
new file mode 100644
index 000000000..5a49c758e
--- /dev/null
+++ b/gui/devices/800x480/res/images/minus-button.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/plus-button.png b/gui/devices/800x480/res/images/plus-button.png
new file mode 100644
index 000000000..da1326c92
--- /dev/null
+++ b/gui/devices/800x480/res/images/plus-button.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/progress_empty.png b/gui/devices/800x480/res/images/progress_empty.png
new file mode 100644
index 000000000..b85371014
--- /dev/null
+++ b/gui/devices/800x480/res/images/progress_empty.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/progress_fill.png b/gui/devices/800x480/res/images/progress_fill.png
new file mode 100644
index 000000000..669c6efa9
--- /dev/null
+++ b/gui/devices/800x480/res/images/progress_fill.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/radio_empty.png b/gui/devices/800x480/res/images/radio_empty.png
new file mode 100644
index 000000000..d118aaf8b
--- /dev/null
+++ b/gui/devices/800x480/res/images/radio_empty.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/radio_selected.png b/gui/devices/800x480/res/images/radio_selected.png
new file mode 100644
index 000000000..5a8a0fd55
--- /dev/null
+++ b/gui/devices/800x480/res/images/radio_selected.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/slider-touch.png b/gui/devices/800x480/res/images/slider-touch.png
new file mode 100644
index 000000000..dee19eec2
--- /dev/null
+++ b/gui/devices/800x480/res/images/slider-touch.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/slider-used.png b/gui/devices/800x480/res/images/slider-used.png
new file mode 100644
index 000000000..754395a21
--- /dev/null
+++ b/gui/devices/800x480/res/images/slider-used.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/slider.png b/gui/devices/800x480/res/images/slider.png
new file mode 100644
index 000000000..b0cc079eb
--- /dev/null
+++ b/gui/devices/800x480/res/images/slider.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/sort-button.png b/gui/devices/800x480/res/images/sort-button.png
new file mode 100644
index 000000000..13ab929de
--- /dev/null
+++ b/gui/devices/800x480/res/images/sort-button.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/twrplogo.png b/gui/devices/800x480/res/images/twrplogo.png
new file mode 100644
index 000000000..309012fc4
--- /dev/null
+++ b/gui/devices/800x480/res/images/twrplogo.png
Binary files differ
diff --git a/gui/devices/800x480/res/images/unlock.png b/gui/devices/800x480/res/images/unlock.png
new file mode 100644
index 000000000..914c60d20
--- /dev/null
+++ b/gui/devices/800x480/res/images/unlock.png
Binary files differ
diff --git a/gui/devices/800x480/res/ui.xml b/gui/devices/800x480/res/ui.xml
new file mode 100644
index 000000000..12e0ee702
--- /dev/null
+++ b/gui/devices/800x480/res/ui.xml
@@ -0,0 +1,465 @@
+<?xml version="1.0"?>
+
+<recovery>
+ <details>
+ <resolution width="800" height="480" />
+ <author>TeamWin</author>
+ <title>Backup Naowz</title>
+ <description>Default basic theme</description>
+ <preview>preview.jpg</preview>
+ </details>
+
+ <include>
+ <xmlfile name="landscape.xml" />
+ </include>
+
+ <resources>
+ <resource name="font" type="font" filename="RobotoCondensed-Regular.ttf" size="16" fallback="Roboto-Condensed-16" />
+ <resource name="fixed" type="font" filename="DroidSansMono.ttf" size="12" />
+ <resource name="twrplogo" type="image" filename="twrplogo" retainaspect="1" />
+ <resource name="main_button" type="image" filename="button" />
+ <resource name="file_icon" type="image" filename="file" retainaspect="1" />
+ <resource name="folder_icon" type="image" filename="folder" retainaspect="1" />
+ <resource name="progress" type="animation" filename="indeterminate" />
+ <resource name="progress_empty" type="image" filename="progress_empty" />
+ <resource name="progress_full" type="image" filename="progress_fill" />
+ <resource name="checkbox_false" type="image" filename="checkbox_empty" retainaspect="1" />
+ <resource name="checkbox_true" type="image" filename="checkbox_checked" retainaspect="1" />
+ <resource name="radio_false" type="image" filename="radio_empty" retainaspect="1" />
+ <resource name="radio_true" type="image" filename="radio_selected" retainaspect="1" />
+ <resource name="medium_button" type="image" filename="medium-button" />
+ <resource name="mediumwide_button" type="image" filename="mediumwide-button" />
+ <resource name="sort_button" type="image" filename="sort-button" />
+ <resource name="minus_button" type="image" filename="minus-button" />
+ <resource name="plus_button" type="image" filename="plus-button" />
+ <resource name="home_icon" type="image" filename="home-icon" retainaspect="1" />
+ <resource name="back_icon" type="image" filename="back-icon" retainaspect="1" />
+ <resource name="console_button" type="image" filename="console-toggle" retainaspect="1" />
+ <resource name="slider" type="image" filename="slider" retainaspect="1" />
+ <resource name="slider-used" type="image" filename="slider-used" retainaspect="1" />
+ <resource name="slider-touch" type="image" filename="slider-touch" retainaspect="1" />
+ <resource name="unlock-icon" type="image" filename="unlock" retainaspect="1" />
+ <resource name="keyboard1" type="image" filename="keyboard1" />
+ <resource name="keyboard2" type="image" filename="keyboard2" />
+ <resource name="keyboard3" type="image" filename="keyboard3" />
+ <resource name="keyboard4" type="image" filename="keyboard4" />
+ <resource name="cursor" type="image" filename="cursor" retainaspect="1" />
+ </resources>
+
+ <variables>
+ <variable name="col1_x" value="23" />
+ <variable name="col2_x" value="210" />
+ <variable name="col3_x" value="410" />
+ <variable name="col4_x" value="610" />
+ <variable name="row1_y" value="90" />
+ <variable name="row2_y" value="340" />
+ <variable name="col_center_x" value="310" />
+ <variable name="center_x" value="400" />
+ <variable name="screen_width" value="800" />
+ <variable name="screen_height" value="480" />
+ <variable name="col_progressbar_x" value="300" />
+ <variable name="row_progressbar_y" value="440" />
+ <variable name="col1_medium_x" value="120" />
+ <variable name="col2_medium_x" value="250" />
+ <variable name="col3_medium_x" value="380" />
+ <variable name="col4_medium_x" value="510" />
+ <variable name="row1_medium_y" value="105" />
+ <variable name="row2_medium_y" value="175" />
+ <variable name="row3_medium_y" value="245" />
+ <variable name="row4_medium_y" value="340" />
+ <variable name="row5_medium_y" value="320" />
+ <variable name="row1_text_y" value="58" />
+ <variable name="row2_text_y" value="78" />
+ <variable name="row3_text_y" value="100" />
+ <variable name="row4_text_y" value="120" />
+ <variable name="row5_text_y" value="140" />
+ <variable name="row6_text_y" value="160" />
+ <variable name="row7_text_y" value="180" />
+ <variable name="row8_text_y" value="200" />
+ <variable name="row9_text_y" value="220" />
+ <variable name="row10_text_y" value="240" />
+ <variable name="row11_text_y" value="260" />
+ <variable name="row12_text_y" value="280" />
+ <variable name="row13_text_y" value="300" />
+ <variable name="row14_text_y" value="320" />
+ <variable name="row15_text_y" value="340" />
+ <variable name="row16_text_y" value="360" />
+ <variable name="row17_text_y" value="380" />
+ <variable name="row18_text_y" value="400" />
+ <variable name="row_offsetmedium_y" value="320" />
+ <variable name="home_button_x" value="589" />
+ <variable name="home_button_y" value="5" />
+ <variable name="back_button_x" value="659" />
+ <variable name="back_button_y" value="5" />
+ <variable name="console_button_x" value="729" />
+ <variable name="console_button_y" value="5" />
+ <variable name="nandcheck_col1" value="23" />
+ <variable name="nandcheck_col2" value="360" />
+ <variable name="nandcheck_row1" value="130" />
+ <variable name="nandcheck_row2" value="160" />
+ <variable name="nandcheck_row3" value="190" />
+ <variable name="nandcheck_row4" value="220" />
+ <variable name="nandcheck_row5" value="250" />
+ <variable name="nandcheck_row6" value="280" />
+ <variable name="nandcheck_row7" value="310" />
+ <variable name="nandcheck_row8" value="340" />
+ <variable name="button_text_color" value="#AAAAAA" />
+ <variable name="text_color" value="#A0A0A0" />
+ <variable name="text_success_color" value="#33B5E5" />
+ <variable name="text_fail_color" value="#FF0101" />
+ <variable name="highlight_color" value="#90909080" />
+ <variable name="caps_highlight_color" value="#33B5E580" />
+ <variable name="slider_x" value="225" />
+ <variable name="slider_y" value="390" />
+ <variable name="slider_text_y" value="425" />
+ <variable name="sort_text_x" value="170" />
+ <variable name="sort_asc_text_y" value="418" />
+ <variable name="sort_asc_button_y" value="413" />
+ <variable name="sort_desc_text_y" value="452" />
+ <variable name="sort_desc_button_y" value="447" />
+ <variable name="sort_col1_button_x" value="300" />
+ <variable name="sort_col2_button_x" value="370" />
+ <variable name="sort_col3_button_x" value="440" />
+ <variable name="col1_sdext_x" value="265" />
+ <variable name="col2_sdext_x" value="475" />
+ <variable name="row1_sdext_y" value="85" />
+ <variable name="row2_sdext_y" value="150" />
+ <variable name="row_extsize_y" value="85" />
+ <variable name="row_swapsize_y" value="150" />
+ <variable name="input_x" value="28" />
+ <variable name="input_width" value="720" />
+ <variable name="input_height" value="25" />
+ <variable name="input_background_color" value="#303030" />
+ <variable name="input_cursor_color" value="#33B5E5" />
+ <variable name="input_cursor_width" value="2" />
+ <variable name="console_x" value="25" />
+ <variable name="console_width" value="750" />
+ <variable name="console_foreground" value="#A0A0A0" />
+ <variable name="warning" value="#F8F8A0" />
+ <variable name="error" value="#FF4040" />
+ <variable name="highlight" value="#33B5E5" />
+ <variable name="console_background" value="#303030" />
+ <variable name="console_scroll" value="#303030" />
+ <variable name="console_action_height" value="230" />
+ <variable name="console_install_height" value="260" />
+ <variable name="console_installdone_height" value="260" />
+ <variable name="fileselector_folder_x" value="28" />
+ <variable name="fileselector_folder_width" value="248" />
+ <variable name="fileselector_folderonly_width" value="400" />
+ <variable name="fileselector_file_x" value="278" />
+ <variable name="fileselector_file_width" value="506" />
+ <variable name="fileselector_install_y" value="120" />
+ <variable name="fileselector_install_height" value="290" />
+ <variable name="fileselector_header_background" value="#202020" />
+ <variable name="fileselector_header_textcolor" value="#AAAAAA" />
+ <variable name="fileselector_header_separatorcolor" value="#33B5E5" />
+ <variable name="fileselector_header_separatorheight" value="2" />
+ <variable name="fileselector_separatorcolor" value="#505050" />
+ <variable name="fileselector_separatorheight" value="1" />
+ <variable name="fileselector_background" value="#303030" />
+ <variable name="fileselector_highlight_color" value="#505050" />
+ <variable name="fileselector_highlight_font_color" value="#33B5E5" />
+ <variable name="fileselector_spacing" value="12" />
+ <variable name="fastscroll_linecolor" value="#50505080" />
+ <variable name="fastscroll_rectcolor" value="#33B5E580" />
+ <variable name="fastscroll_w" value="25" />
+ <variable name="fastscroll_linew" value="2" />
+ <variable name="fastscroll_rectw" value="12" />
+ <variable name="fastscroll_recth" value="20" />
+ <variable name="zipstorage_text_y" value="88" />
+ <variable name="listbox_x" value="156" />
+ <variable name="listbox_y" value="90" />
+ <variable name="listbox_width" value="460" />
+ <variable name="listbox_tz_height" value="170" />
+ <variable name="listbox_background" value="#303030" />
+ <variable name="listbox_spacing" value="12" />
+ <variable name="sd_plus_x" value="280" />
+ <variable name="lock_y" value="150" />
+ <variable name="filemanager_select_x" value="610" />
+ <variable name="filemanager_select_y" value="413" />
+ <variable name="backup_name_text_y" value="440" />
+ <variable name="backup_name_button_y" value="195" />
+ <variable name="col_right_x" value="772" />
+ <variable name="cancel_button_y" value="180" />
+ <variable name="terminal_console_y" value="0" />
+ <variable name="terminal_console_height" value="240" />
+ <variable name="terminal_text_y" value="247" />
+ <variable name="terminal_button_y" value="237" />
+ <variable name="terminal_input_width" value="551" />
+ <variable name="button_fill_color" value="#303030" />
+ <variable name="button_fill_full_width" value="400" />
+ <variable name="button_fill_main_width" value="367" />
+ <variable name="button_fill_main_height" value="120" />
+ <variable name="button_fill_half_height" value="40" />
+ <variable name="button_fill_quarter_height" value="30" />
+ <variable name="button_full_center_x" value="200" />
+ <variable name="flash_list_height" value="140" />
+ <variable name="backup_list_x" value="23" />
+ <variable name="backup_list_y" value="80" />
+ <variable name="backup_list_width" value="367" />
+ <variable name="backup_list_height" value="290" />
+ <variable name="backup_storage_y" value="190" />
+ <variable name="backup_encrypt_y" value="235" />
+ <variable name="restore_list_y" value="100" />
+ <variable name="restore_list_height" value="270" />
+ <variable name="mount_list_height" value="360" />
+ <variable name="mount_storage_row" value="500" />
+ <variable name="wipe_list_height" value="300" />
+ <variable name="wipe_button_y" value="150" />
+ <variable name="slidervalue_x" value="200" />
+ <variable name="slidervalue_w" value="400" />
+ <variable name="slidervalue_line_clr" value="#FFFFFF" />
+ <variable name="slidervalue_slider_clr" value="#33B5E5" />
+ <variable name="slidervalue_lineh" value="1" />
+ <variable name="slidervalue_padding" value="0" />
+ <variable name="slidervalue_sliderw" value="7" />
+ <variable name="slidervalue_sliderh" value="40" />
+ <variable name="pattern_x" value="200" />
+ <variable name="pattern_y" value="110" />
+ <variable name="pattern_width" value="300" />
+ <variable name="pattern_dot_color" value="#33B5E5" />
+ <variable name="pattern_dot_color_active" value="#FFFFFF" />
+ <variable name="pattern_dot_radius" value="10" />
+ <variable name="pattern_line_color" value="#33B5E5" />
+ <variable name="pattern_line_width" value="7" />
+ </variables>
+
+ <mousecursor>
+ <placement w="15" h="15" />
+ <background color="#FFFF00FF" resource="cursor" />
+ <speed multiplier="1.5" />
+ </mousecursor>
+
+ <templates>
+ <template name="header">
+ <background color="#000000FF" />
+
+ <object type="fill" color="%button_fill_color%">
+ <placement x="0" y="0" w="800" h="58" />
+ </object>
+
+ <object type="fill" color="%highlight%">
+ <placement x="0" y="58" w="800" h="2" />
+ </object>
+
+ <object type="image">
+ <image resource="twrplogo" />
+ <placement x="35" y="29" placement="4" />
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="70" y="2" />
+ <text>Team Win Recovery Project v%tw_version%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="70" y="37" />
+ <conditions>
+ <condition var1="tw_no_battery_percent" var2="0" />
+ <condition var1="tw_battery" op="&gt;" var2="0" />
+ <condition var1="tw_battery" op="&lt;" var2="101" />
+ </conditions>
+ <text>Battery Level: %tw_battery%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="425" y="37" />
+ <text>%tw_time%</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="500" y="37" />
+ <conditions>
+ <condition var1="tw_no_cpu_temp" var2="0" />
+ </conditions>
+ <text>CPU: %tw_cpu_temp% C</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <condition var1="tw_simulate_actions" var2="1" />
+ <font resource="font" />
+ <placement x="250" y="20" />
+ <text>SIMULATING ACTIONS</text>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%home_button_x%" y="%home_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="home_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">home</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%back_button_x%" y="%back_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text></text>
+ <image resource="back_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">back</action>
+ </object>
+
+ <object type="action">
+ <touch key="power" />
+ <action function="overlay">lock</action>
+ </object>
+
+ <object type="action">
+ <touch key="power+voldown" />
+ <action function="screenshot" />
+ </object>
+ </template>
+
+ <template name="progress_bar">
+ <object type="progressbar">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource empty="progress_empty" full="progress_full" />
+ <data name="ui_progress" />
+ </object>
+
+ <object type="animation">
+ <placement x="%col_progressbar_x%" y="%row_progressbar_y%" />
+ <resource name="progress" />
+ <speed fps="15" render="2" />
+ <loop frame="1" />
+ </object>
+ </template>
+
+ <template name="sort_options">
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="%sort_text_x%" y="%sort_asc_text_y%" />
+ <text>Sort Ascending:</text>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col1_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=1</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col2_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=2</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col3_button_x%" y="%sort_asc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=3</action>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <font resource="font" />
+ <placement x="%sort_text_x%" y="%sort_desc_text_y%" />
+ <text>Sort Descending:</text>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col1_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Name</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-1</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col2_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Date</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-2</action>
+ </object>
+
+ <object type="button">
+ <highlight color="%highlight_color%" />
+ <placement x="%sort_col3_button_x%" y="%sort_desc_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>Size</text>
+ <image resource="sort_button" />
+ <action function="set">tw_gui_sort_order=-3</action>
+ </object>
+ </template>
+
+ <template name="flash_zip_console">
+ <object type="console">
+ <placement x="%console_x%" y="85" w="%console_width%" h="260" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="action_page_console">
+ <object type="console">
+ <placement x="%console_x%" y="160" w="%console_width%" h="230" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="footer">
+ <object type="console">
+ <slideout resource="console_button" x="%console_button_x%" y="%console_button_y%" />
+ <placement x="%console_x%" y="60" w="%console_width%" h="380" />
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ </object>
+ </template>
+
+ <template name="keyboardtemplate">
+ <object type="keyboard">
+ <placement x="0" y="277" />
+ <layout resource1="keyboard1" resource2="keyboard2" resource3="keyboard3" resource4="keyboard4" />
+ <highlight color="%highlight_color%" />
+ <capshighlight color="%caps_highlight_color%" />
+ <layout1>
+ <keysize height="51" width="73" />
+ <row1 key01="q" long01="1" key02="w" long02="2" key03="e" long03="3" key04="r" long04="4" key05="t" long05="5" key06="y" long06="6" key07="u" long07="7" key08="i" long08="8" key09="o" long09="9" key10="p" long10="0" key11="70:c:8" />
+ <row2 key01="107:a" key02="s" key03="d" key04="f" key05="g" key06="h" key07="j" key08="k" key09="l" key10="109:action" />
+ <row3 key01="79:layout2" key02="72:z" key03="72:x" key04="72:c" key05="72:v" key06="72:b" key07="72:n" key08="72:m" key09="72:," long09="!" key10="72:." long10="?" key11="73::" long11="+" />
+ <row4 key01="103:layout3" key02="72:" key03="/" long03="@" key04="315: " key05="'" long05="73:c:34" key06="-" long06="_" />
+ </layout1>
+ <layout2>
+ <keysize height="51" width="73" capslock="0" revert_layout="1" />
+ <row1 key01="Q" long01="1" key02="W" long02="2" key03="E" long03="3" key04="R" long04="4" key05="T" long05="5" key06="Y" long06="6" key07="U" long07="7" key08="I" long08="8" key09="O" long09="9" key10="P" long10="0" key11="70:c:8" />
+ <row2 key01="107:A" key02="S" key03="D" key04="F" key05="G" key06="H" key07="J" key08="K" key09="L" key10="109:action" />
+ <row3 key01="79:layout1" key02="72:Z" key03="72:X" key04="72:C" key05="72:V" key06="72:B" key07="72:N" key08="72:M" key09="72:," long09="!" key10="72:." long10="?" key11="73::" long11="+" />
+ <row4 key01="103:layout3" key02="72:" key03="/" long03="@" key04="315: " key05="'" long05="73:c:34" key06="-" long06="_" />
+ </layout2>
+ <layout3>
+ <keysize height="51" width="73" />
+ <row1 key01="1" key02="2" key03="3" key04="4" key05="5" key06="6" key07="7" key08="8" key09="9" key10="0" key11="70:c:8" />
+ <row2 key01="107:#" key02="$" key03="%" key04="&amp;" key05="*" key06="-" key07="+" key08="(" key09=")" key10="109:action" />
+ <row3 key01="79:layout4" key02="72:&lt;" key03="72:&gt;" key04="72:=" key05="72::" key06="72:;" key07="72:," key08="72:." key09="72:!" key10="72:?" key11="73:/" />
+ <row4 key01="103:layout1" key02="72:" key03="@" key04="315: " key05="73:c:34" key06="_" />
+ </layout3>
+ <layout4>
+ <keysize height="51" width="73" />
+ <row1 key01="~" key02="`" key03="|" key04="73:" key05="73:" key06="73:" key07="73:" key08="73:" key09="73:" key10="73:" key11="70:c:8" />
+ <row2 key01="107:" key02="73:" key03="73:" key04="73:" key05="^" key06="73:" key07="73:" key08="{" key09="}" key10="109:action" />
+ <row3 key01="79:layout3" key02="72:\" key03="72:" key04="72:" key05="72:" key06="72:" key07="72:[" key08="72:]" key09="72:!" key10="72:?" />
+ <row4 key01="103:layout1" key02="72:" key03="72:" key04="315: " />
+ </layout4>
+ </object>
+ </template>
+ </templates>
+</recovery>
diff --git a/gui/devices/common/res/fonts/DroidSansMono.ttf b/gui/devices/common/res/fonts/DroidSansMono.ttf
new file mode 100644
index 000000000..4085cee84
--- /dev/null
+++ b/gui/devices/common/res/fonts/DroidSansMono.ttf
Binary files differ
diff --git a/gui/devices/common/res/fonts/RobotoCondensed-Regular.ttf b/gui/devices/common/res/fonts/RobotoCondensed-Regular.ttf
new file mode 100644
index 000000000..b9fc49c95
--- /dev/null
+++ b/gui/devices/common/res/fonts/RobotoCondensed-Regular.ttf
Binary files differ
diff --git a/gui/devices/common/res/images/progress_empty.png b/gui/devices/common/res/images/progress_empty.png
new file mode 100644
index 000000000..b85371014
--- /dev/null
+++ b/gui/devices/common/res/images/progress_empty.png
Binary files differ
diff --git a/gui/devices/common/res/images/progress_fill.png b/gui/devices/common/res/images/progress_fill.png
new file mode 100644
index 000000000..6731dae4a
--- /dev/null
+++ b/gui/devices/common/res/images/progress_fill.png
Binary files differ
diff --git a/gui/devices/landscape/res/landscape.xml b/gui/devices/landscape/res/landscape.xml
new file mode 100644
index 000000000..c75be3c6f
--- /dev/null
+++ b/gui/devices/landscape/res/landscape.xml
@@ -0,0 +1,3714 @@
+<?xml version="1.0"?>
+
+<recovery>
+ <styles>
+ <style name="buttontext">
+ <highlight color="%highlight_color%" />
+ <font resource="font" color="%button_text_color%" />
+ </style>
+
+ <style name="button">
+ <style name="buttontext" />
+ <image resource="main_button" />
+ </style>
+
+ <style name="mediumbutton">
+ <style name="buttontext" />
+ <image resource="medium_button" />
+ </style>
+
+ <style name="mediumwidebutton">
+ <style name="buttontext" />
+ <image resource="mediumwide_button" />
+ </style>
+
+ <style name="fillbutton">
+ <style name="buttontext" />
+ <fill color="%button_fill_color%" />
+ </style>
+
+ <style name="rebootsystem">
+ <condition var1="tw_reboot_system" var2="1" />
+ <style name="button" />
+ <text>Reboot System</text>
+ <actions>
+ <action function="set">tw_back=main2</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=system</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_text3=</action>
+ <action function="set">tw_text4=</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </style>
+
+ <style name="scrolllist">
+ <highlight color="%fileselector_highlight_color%" />
+ <header background="%fileselector_header_background%" textcolor="%fileselector_header_textcolor%" separatorcolor="%fileselector_header_separatorcolor%" separatorheight="%fileselector_header_separatorheight%" />
+ <fastscroll linecolor="%fastscroll_linecolor%" rectcolor="%fastscroll_rectcolor%" w="%fastscroll_w%" linew="%fastscroll_linew%" rectw="%fastscroll_rectw%" recth="%fastscroll_recth%" />
+ <separator color="%fileselector_separatorcolor%" height="%fileselector_separatorheight%" />
+ <background color="%fileselector_background%" />
+ <font resource="font" spacing="%fileselector_spacing%" color="%text_color%" highlightcolor="%fileselector_highlight_font_color%" />
+ </style>
+
+ <style name="fileselector">
+ <style name="scrolllist" />
+ <icon folder="folder_icon" file="file_icon" />
+ <sort name="tw_gui_sort_order" />
+ </style>
+
+ <style name="partitionlist">
+ <style name="scrolllist" />
+ <icon selected="checkbox_true" unselected="checkbox_false" />
+ </style>
+
+ <style name="text">
+ <font resource="font" color="%text_color%" />
+ </style>
+
+ <style name="checkbox">
+ <font resource="font" color="%text_color%" />
+ <image checked="checkbox_true" unchecked="checkbox_false" />
+ </style>
+
+ <style name="slider">
+ <text>Swipe to Confirm</text>
+ <font resource="font" color="%text_color%" />
+ <placement x="%center_x%" y="%slider_y%" placement="5" />
+ <resource base="slider" used="slider-used" touch="slider-touch" />
+ </style>
+
+ <style name="console">
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ <fastscroll linecolor="%fastscroll_linecolor%" rectcolor="%fastscroll_rectcolor%" w="%fastscroll_w%" linew="%fastscroll_linew%" rectw="%fastscroll_rectw%" recth="%fastscroll_recth%" />
+ </style>
+
+ <style name="input">
+ <background color="%input_background_color%" />
+ <cursor color="%input_cursor_color%" hasfocus="1" width="%input_cursor_width%" />
+ <font resource="font" color="%text_color%" />
+ </style>
+
+ <style name="slidervalue">
+ <font resource="font" color="%text_color%" />
+ <colors line="%slidervalue_line_clr%" slider="%slidervalue_slider_clr%" />
+ <dimensions lineh="%slidervalue_lineh%" linepadding="%slidervalue_padding%" sliderw="%slidervalue_sliderw%" sliderh="%slidervalue_sliderh%" />
+ </style>
+ </styles>
+
+ <pages>
+ <page name="main">
+ <object type="action">
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="main2">
+ <object type="template" name="header" />
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Install</text>
+ <actions>
+ <action function="queueclear"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Backup</text>
+ <action function="page">backup</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row1_y%" />
+ <text>Restore</text>
+ <action function="page">restore</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%row1_y%" />
+ <text>Wipe</text>
+ <action function="page">wipe</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Mount</text>
+ <action function="page">mount</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Settings</text>
+ <action function="page">settings</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row2_y%" />
+ <text>Advanced</text>
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%row2_y%" />
+ <text>Reboot</text>
+ <action function="page">reboot</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="install">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Select Zip to Install</text>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%button_full_center_x%" y="%zipstorage_text_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=install</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_folder_x%" y="%fileselector_install_y%" w="%fileselector_folder_width%" h="%fileselector_install_height%" />
+ <text>Folders:</text>
+ <filter folders="1" files="0" />
+ <path name="tw_zip_location" default="/sdcard" />
+ <data name="select" />
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_file_x%" y="%fileselector_install_y%" w="%fileselector_file_width%" h="%fileselector_install_height%" />
+ <text>%tw_zip_location%</text>
+ <filter extn=".zip" folders="0" files="1" />
+ <path name="tw_zip_location" />
+ <data name="tw_filename" />
+ <selection name="tw_file" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="button">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Images...</text>
+ <actions>
+ <action function="page">install_image</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_filename" op="modified" />
+ <actions>
+ <action function="queuezip"></action>
+ <action function="page">flash_confirm</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="flash_confirm">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>WARNING: This operation may install incompatible software and render your device unusable.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Folder:</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_zip_location%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>File to flash:</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>%tw_file%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row6_text_y%" placement="5" />
+ <text>Press back to cancel adding this zip.</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col2_x%" y="%row7_text_y%" />
+ <text>Zip file signature verification?</text>
+ <data variable="tw_signed_zip_verify" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row10_text_y%" placement="5" />
+ <text>File %tw_zip_queue_count% of max of 10</text>
+ </object>
+
+ <object type="button" style="mediumwidebutton">
+ <condition var1="tw_zip_queue_count" op="!=" var2="10"></condition>
+ <placement x="%col2_x%" y="%row5_medium_y%" />
+ <text>Add More Zips</text>
+ <action function="page">install</action>
+ </object>
+
+ <object type="button" style="mediumwidebutton">
+ <placement x="%col3_x%" y="%row5_medium_y%" />
+ <text>Clear Queue</text>
+ <actions>
+ <action function="queueclear"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Confirm Flash</text>
+ <action function="flash">flash_zip</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="cancelzip"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="flash_zip">
+ <object type="template" name="header" />
+
+ <object type="template" name="flash_zip_console" />
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row16_text_y%" />
+ <text>Flashing file %tw_zip_index% of %tw_zip_queue_count%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row17_text_y%" />
+ <text>%tw_filename%</text>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <action function="page">flash_done</action>
+ </object>
+ </page>
+
+ <page name="flash_done">
+ <object type="template" name="header" />
+
+ <object type="template" name="flash_zip_console" />
+
+ <object type="text">
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row17_text_y%" placement="5" />
+ <text>Failed</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" var2="0" />
+ <font resource="font" color="%text_success_color%" />
+ <placement x="%center_x%" y="%row17_text_y%" placement="5" />
+ <text>Successful</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%slider_y%" />
+ <text>Wipe Cache/Dalvik</text>
+ <actions>
+ <action function="set">tw_back=flash_done</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=/cache</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=wipe</action>
+ <action function="set">tw_action2_param=dalvik</action>
+ <action function="set">tw_text1=Wipe Cache &amp; Dalvik?</action>
+ <action function="set">tw_action_text1=Wiping Cache &amp; Dalvik...</action>
+ <action function="set">tw_complete_text1=Cache &amp; Dalvik Wipe Complete</action>
+ <action function="set">tw_slider_text=Swipe to Wipe</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button" style="rebootsystem">
+ <placement x="%col4_x%" y="%slider_y%" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%slider_y%" />
+ <text>Home</text>
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=install</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="install_image">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Select Image to Flash</text>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%button_full_center_x%" y="%zipstorage_text_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=install_image</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_folder_x%" y="%fileselector_install_y%" w="%fileselector_folder_width%" h="%fileselector_install_height%" />
+ <text>Folders:</text>
+ <filter folders="1" files="0" />
+ <path name="tw_zip_location" default="/sdcard" />
+ <data name="select" />
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_file_x%" y="%fileselector_install_y%" w="%fileselector_file_width%" h="%fileselector_install_height%" />
+ <text>%tw_zip_location%</text>
+ <filter extn=".img" folders="0" files="1" />
+ <path name="tw_zip_location" />
+ <data name="tw_filename" />
+ <selection name="tw_file" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="button">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Zips...</text>
+ <actions>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_filename" op="modified" />
+ <action function="page">flashimage_confirm</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">install</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="flashimage_confirm">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%col2_x%" y="%row1_text_y%" w="%listbox_width%" h="%flash_list_height%" />
+ <text>Select Partition to Flash Image:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_flash_partition" />
+ <listtype name="flashimg" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row8_text_y%" placement="5" />
+ <text>Folder:</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row9_text_y%" placement="5" />
+ <text>%tw_zip_location%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row10_text_y%" placement="5" />
+ <text>File to flash:</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row11_text_y%" placement="5" />
+ <text>%tw_file%</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Confirm Flash</text>
+ <actions>
+ <action function="set">tw_back=flashimage_confirm</action>
+ <action function="set">tw_action=flashimage</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_action_text1=Flashing Image...</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_complete_text1=Image Flashed</action>
+ <action function="page">action_page</action>
+ </actions>
+ <action function="flashimage"></action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=install_image</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="clear_vars">
+ <object type="action">
+ <action function="set">tw_operation_state=0</action>
+ <action function="set">tw_text1=</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_text3=</action>
+ <action function="set">tw_text4=</action>
+ <action function="set">tw_action_text1=</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_action_param=</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_action2=</action>
+ <action function="set">tw_action2_param=</action>
+ <action function="set">tw_has_cancel=0</action>
+ <action function="set">tw_cancel_action=</action>
+ <action function="set">tw_cancel_param=</action>
+ <action function="set">tw_show_exclamation=0</action>
+ <action function="set">tw_show_reboot=0</action>
+ <action function="page">%tw_clear_destination%</action>
+ </object>
+ </page>
+
+ <page name="confirm_action">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_text2%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_text3%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>%tw_text4%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row12_text_y%" placement="5" />
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="slider">
+ <text>%tw_slider_text%</text>
+ <action function="page">action_page</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="action_page">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_action_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_action_text2%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="button">
+ <condition var1="tw_has_cancel" var2="1" />
+ <placement x="%col_center_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <action function="%tw_cancel_action%">%tw_cancel_param%</action>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="0" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="1" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ <action function="%tw_action2%">%tw_action2_param%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="singleaction_page">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_action_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_action_text2%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="0" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="1" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ <action function="%tw_action2%">%tw_action2_param%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="action_complete">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_complete_text1%</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Failed</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" var2="0" />
+ <font resource="font" color="%text_success_color%" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Successful</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="button">
+ <condition var1="tw_show_reboot" var2="0" />
+ <placement x="%col_center_x%" y="%slider_y%" />
+ <text>Back</text>
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="button" style="rebootsystem">
+ <condition var1="tw_show_reboot" var2="1" />
+ <placement x="%col_center_x%" y="%slider_y%" />
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="filecheck">
+ <object type="action">
+ <action function="fileexists">%tw_filecheck%</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_fileexists=1</action>
+ <action function="page">%tw_existpage%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="1" />
+ </conditions>
+ <actions>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">%tw_notexistpage%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="rebootcheck">
+ <object type="action">
+ <condition var1="tw_backup_system_size" op="&gt;=" var2="%tw_min_system%" />
+ <action function="reboot">%tw_action_param%</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_backup_system_size" op="&lt;" var2="%tw_min_system%" />
+ <action function="page">confirm_action</action>
+ </object>
+ </page>
+
+ <page name="reboot">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Reboot Menu</text>
+ </object>
+
+ <object type="button" style="rebootsystem">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>System</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_poweroff" var2="1" />
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Power Off</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=poweroff</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to power off?</action>
+ <action function="set">tw_action_text1=Turning Off...</action>
+ <action function="set">tw_complete_text1=Turning Off...</action>
+ <action function="set">tw_slider_text=Swipe to Power Off</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_recovery" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Recovery</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=recovery</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_bootloader" var2="1" />
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Bootloader</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=bootloader</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_download_mode" var2="1" />
+ <placement x="%col3_x%" y="%row2_y%" />
+ <text>Download</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=download</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="selectstorage">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%col2_x%" y="%fileselector_install_y%" w="%fileselector_folderonly_width%" h="%fileselector_install_height%" />
+ <text>Select Storage:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_storage_path" />
+ <listtype name="storage" />
+ </object>
+
+ <object type="button">
+ <placement x="%filemanager_select_x%" y="%row2_y%" />
+ <text>OK</text>
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="mount">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Mount Menu</text>
+ </object>
+
+ <object type="partitionlist">
+ <placement x="%backup_list_x%" y="%backup_list_y%" w="%backup_list_width%" h="%mount_list_height%" />
+ <text>Select Partitions to Mount:</text>
+ <listtype name="mount" />
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_is_encrypted" var2="1" />
+ <condition var1="tw_is_decrypted" var2="0" />
+ </conditions>
+ <placement x="%col3_x%" y="row1_y" />
+ <text>Decrypt Data</text>
+ <action function="page">decrypt</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_has_usb_storage" var2="1" />
+ <placement x="%col4_x%" y="%row1_y%" />
+ <text>Mount USB Storage</text>
+ <action function="page">usb_mount</action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_has_mtp" var2="1" />
+ <condition var1="tw_mtp_enabled" var2="0" />
+ </conditions>
+ <placement x="%col3_x%" y="row1_y" />
+ <text>Enable MTP</text>
+ <action function="startmtp"></action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_has_mtp" var2="1" />
+ <condition var1="tw_mtp_enabled" var2="1" />
+ </conditions>
+ <placement x="%col3_x%" y="row1_y" />
+ <text>Disable MTP</text>
+ <action function="stopmtp"></action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_is_encrypted" var2="1" />
+ <condition var1="tw_is_decrypted" var2="0" />
+ </conditions>
+ <placement x="%col3_x%" y="row1_y" />
+ <text>Decrypt Data</text>
+ <action function="page">decrypt</action>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col3_x%" y="%backup_storage_y%" w="%button_fill_main_width%" h="%button_fill_half_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row10_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_false" />
+ <action function="mountsystemtoggle">1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row10_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="!=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_true" />
+ <actions>
+ <action function="set">tw_lifetime_writes=2</action>
+ <action function="page">system_readonly_check</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="usb_mount">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>USB Storage Mounted -- Be sure to safely remove your device from your computer before unmounting!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row1_y%" />
+ <text>Unmount</text>
+ <action function="page">usb_umount</action>
+ </object>
+
+ <object type="action">
+ <action function="mount">usb</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="usb_umount">
+ <object type="action">
+ <action function="unmount">usb</action>
+ </object>
+
+ <object type="action">
+ <action function="page">mount</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="system_readonly_check">
+ <object type="action">
+ <action function="checkpartitionlifetimewrites">/system</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_lifetime_writes" var2="1" />
+ <actions>
+ <action function="mountsystemtoggle">0</action>
+ <action function="page">mount</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_lifetime_writes" var2="0" />
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">system_readonly</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="wipe">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Factory Reset: Wipes Data, Cache, and Dalvik</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_has_data_media" var2="1" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>(not including internal storage)</text>
+ </object>
+
+ <object type="text">
+ <conditions>
+ <condition var1="tw_has_android_secure" var2="1" />
+ <condition var1="fileexists" var2="/and-sec" />
+ </conditions>
+ <placement x="%center_x%" y="%row3_text_y%" placement="1" />
+ <text>Android Secure </text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_has_sdext_partition" var2="1" />
+ <placement x="%center_x%" y="%row3_text_y%" />
+ <text> SD-EXT</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Most of the time this is the only wipe that you need.</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%wipe_button_y%" />
+ <text>Advanced Wipe</text>
+ <action function="page">advancedwipe</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_has_data_media" var2="1" />
+ <placement x="%col3_x%" y="%wipe_button_y%" />
+ <text>Format Data</text>
+ <actions>
+ <action function="page">formatdata</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_is_encrypted" var2="1" />
+ <condition var1="tw_has_data_media" var2="0" />
+ </conditions>
+ <placement x="%col3_x%" y="%wipe_button_y%" />
+ <text>Wipe Encryption</text>
+ <actions>
+ <action function="set">tw_back=wipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=DATAMEDIA</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Wipe Encryption from Data?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting Data...</action>
+ <action function="set">tw_complete_text1=Data Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Format Data</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row12_text_y%" placement="5" />
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Factory Reset</text>
+ <actions>
+ <action function="set">tw_back=wipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=data</action>
+ <action function="set">tw_action_text1=Factory Reset...</action>
+ <action function="set">tw_complete_text1=Factory Reset Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="advancedwipe">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%backup_list_x%" y="%backup_list_y%" w="%backup_list_width%" h="%backup_list_height%" />
+ <text>Select Partitions to Wipe:</text>
+ <data name="tw_wipe_list" />
+ <listtype name="wipe" />
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col3_x%" y="%backup_storage_y%" w="%button_fill_main_width%" h="%button_fill_half_height%" />
+ <text>Repair or Change File System</text>
+ <actions>
+ <action function="checkpartitionlist"></action>
+ <action function="page">checkpartitionlist</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="partitionlisterror" var2="1" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%col3_x%" y="%backup_storage_y%" />
+ <text>Invalid partition selection</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Wipe</text>
+ <actions>
+ <action function="set">tw_back=advancedwipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=LIST</action>
+ <action function="set">tw_text1=Wipe Selected Partition(s)?</action>
+ <action function="set">tw_action_text1=Wiping Partition(s)...</action>
+ <action function="set">tw_complete_text1=Wipe Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">wipe</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="formatdata">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Format Data will wipe all of your apps, backups, pictures,</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>videos, media, and removes encryption on internal storage.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>This cannot be undone. Press back to cancel.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Type yes to continue.</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row6_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_confirm_formatdata%</text>
+ <data name="tw_confirm_formatdata" />
+ <restrict minlen="3" maxlen="3" allow="yes" />
+ <action function="page">formatdata_confirm</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">wipe</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="formatdata_confirm">
+ <object type="action">
+ <condition var1="tw_confirm_formatdata" op="=" var2="yes" />
+ <actions>
+ <action function="set">tw_back=formatdata</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=DATAMEDIA</action>
+ <action function="set">tw_action_text1=Formatting Data...</action>
+ <action function="set">tw_complete_text1=Data Format Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_confirm_formatdata" op="!=" var2="yes" />
+ <action function="page">formatdata</action>
+ </object>
+ </page>
+
+ <page name="checkpartitionlist">
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=0</action>
+ <action function="getpartitiondetails"></action>
+ <action function="page">partitionoptions</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="!=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=1</action>
+ <action function="set">tw_wipe_list=</action>
+ <action function="page">advancedwipe</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="partitionoptions">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row1_text_y%" />
+ <text>Partition Options for: %tw_partition_name%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col_right_x%" y="%row1_text_y%" placement="1" />
+ <text>Mount Point: %tw_partition_mount_point%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Current file system: %tw_partition_file_system%</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_is_present" op="!=" var2="0" />
+ <placement x="%col2_x%" y="%row3_text_y%" />
+ <text>Present: Yes</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_is_present" op="=" var2="0" />
+ <placement x="%col2_x%" y="%row3_text_y%" />
+ <text>Present: No</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_removable" op="!=" var2="0" />
+ <placement x="%col3_x%" y="%row3_text_y%" />
+ <text>Removable: Yes</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_removable" op="=" var2="0" />
+ <placement x="%col3_x%" y="%row3_text_y%" />
+ <text>Removable: No</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Size: %tw_partition_size%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col2_x%" y="%row4_text_y%" />
+ <text>Used: %tw_partition_used%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col3_x%" y="%row4_text_y%" />
+ <text>Free: %tw_partition_free%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col4_x%" y="%row4_text_y%" />
+ <text>Backup Size: %tw_partition_backup_size%MB</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_can_resize" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Resize</text>
+ <actions>
+ <action function="set">tw_back=partitionoptions</action>
+ <action function="set">tw_action=resize</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=getpartitiondetails</action>
+ <action function="set">tw_text1=Resize %tw_partition_name%?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Resizing...</action>
+ <action function="set">tw_complete_text1=Resize Complete</action>
+ <action function="set">tw_slider_text=Swipe to Resize</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_can_repair" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Repair</text>
+ <actions>
+ <action function="set">tw_back=partitionoptions</action>
+ <action function="set">tw_action=repair</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Repair %tw_partition_name%?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Repairing...</action>
+ <action function="set">tw_complete_text1=Repair Complete</action>
+ <action function="set">tw_slider_text=Swipe to Repair</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row2_y%" />
+ <text>Change File System</text>
+ <action function="page">selectfilesystem</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advancedwipe</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="refreshfilesystem">
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=0</action>
+ <action function="getpartitiondetails"></action>
+ <action function="page">selectfilesystem</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="!=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=1</action>
+ <action function="set">tw_wipe_list=</action>
+ <action function="page">advancedwipe</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="selectfilesystem">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row1_text_y%" />
+ <text>Change file system for: %tw_partition_name%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col_right_x%" y="%row1_text_y%" placement="1" />
+ <text>Mount Point: %tw_partition_mount_point%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Current file system: %tw_partition_file_system%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Some ROMs or kernels may not support some file systems. Proceed with caution!</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>EXT2</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext2</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT2?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>EXT3</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext3</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT3?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col3_x%" y="%row1_y%" />
+ <text>EXT4</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext4</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT4?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_f2fs" op="=" var2="1" />
+ <placement x="%col4_x%" y="%row1_y%" />
+ <text>F2FS</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=f2fs</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to F2FS?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_vfat" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>FAT</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=vfat</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to FAT?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_exfat" op="=" var2="1" />
+ <placement x="%col3_x%" y="%row2_y%" />
+ <text>exFAT</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=exfat</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to exFAT?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">partitionoptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backup">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Back Up Device</text>
+ </object>
+
+ <object type="partitionlist">
+ <placement x="%backup_list_x%" y="%backup_list_y%" w="%backup_list_width%" h="%backup_list_height%" />
+ <text>Select Partitions to Back Up:</text>
+ <data name="tw_backup_list" />
+ <listtype name="backup" />
+ </object>
+
+ <object type="text">
+ <placement x="%col_right_x%" y="%row2_text_y%" placement="1" />
+ <text>Backup Name: %tw_backup_name%</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row1_y%" />
+ <text>Refresh Sizes</text>
+ <actions>
+ <action function="refreshsizes"></action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%row1_y%" />
+ <text>Set Backup Name</text>
+ <actions>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">backupname1</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col3_x%" y="%backup_storage_y%" w="%button_fill_main_width%" h="%button_fill_half_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <conditions>
+ <condition var1="tw_include_encrypted_backup" var2="1" />
+ <condition var1="tw_encrypt_backup" var2="0" />
+ </conditions>
+ <placement x="%col3_x%" y="%backup_encrypt_y%" w="%button_fill_main_width%" h="%button_fill_half_height%" />
+ <text>No Encryption</text>
+ <actions>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <conditions>
+ <condition var1="tw_include_encrypted_backup" var2="1" />
+ <condition var1="tw_encrypt_backup" var2="1" />
+ </conditions>
+ <placement x="%col3_x%" y="%backup_encrypt_y%" w="%button_fill_main_width%" h="%button_fill_half_height%" />
+ <text>Using Encryption</text>
+ <actions>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col3_x%" y="%nandcheck_row6%" />
+ <text>Enable Compression (Requires more time)</text>
+ <data variable="tw_use_compression" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col3_x%" y="%nandcheck_row7%" />
+ <text>Skip MD5 generation on backups</text>
+ <data variable="tw_skip_md5_generate" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col3_x%" y="%nandcheck_row8%" />
+ <font resource="font" color="%text_color%" />
+ <text>Disable Free Space Check.</text>
+ <data variable="tw_disable_free_space" />
+ <image checked="checkbox_true" unchecked="checkbox_false" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Back Up</text>
+ <actions>
+ <action function="set">tw_operation_state=0</action>
+ <action function="page">backup_run</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backupname1">
+ <object type="action">
+ <condition var1="tw_backup_name" op="=" var2="(Auto Generate)" />
+ <action function="generatebackupname"></action>
+ </object>
+
+ <object type="action">
+ <action function="page">backupname2</action>
+ </object>
+ </page>
+
+ <page name="backupname2">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter a Backup Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_name%</text>
+ <data name="tw_backup_name" />
+ <restrict minlen="1" maxlen="64" allow=" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_.{}[]" />
+ <actions>
+ <action function="set">tw_filecheck=%tw_backups_folder%/%tw_backup_name%</action>
+ <action function="set">tw_existpage=backupname2</action>
+ <action function="set">tw_notexistpage=backup</action>
+ <action function="page">filecheck</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_fileexists" var2="1" />
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <font resource="font" color="%text_fail_color%"/>
+ <text>A backup with that name already exists!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%cancel_button_y%" />
+ <text>Append Date</text>
+ <action function="appenddatetobackupname"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%cancel_button_y%" />
+ <text>Cancel / Clear</text>
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backupencryption">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Encrypt your backup? Please enter a password:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_encrypt_display%</text>
+ <data name="tw_backup_password" mask="*" maskvariable="tw_backup_encrypt_display" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <action function="page">backupencryption2</action>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_not_match" var2="1" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Passwords Do Not Match</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">backup</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backupencryption2">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Encrypt your backup? Please Enter Password Again:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_encrypt_display2%</text>
+ <data name="tw_backup_password2" mask="*" maskvariable="tw_backup_encrypt_display2" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <actions>
+ <action function="page">checkbackuppassword</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">backup</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="checkbackuppassword">
+ <object type="action">
+ <condition var1="tw_backup_password2" var2="tw_backup_password" />
+ <actions>
+ <action function="set">tw_encrypt_backup=1</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_backup_password2" op="!=" var2="tw_backup_password" />
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_password_not_match=1</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="backup_run">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_operation% %tw_partition%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>%tw_file_progress%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col_right_x%" y="%row2_text_y%" placement="1" />
+ <text>%tw_size_progress%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="cancelbackup"></action>
+ </actions>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="nandroid">backup</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_cancel_backup" var2="0" />
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="set">tw_complete_text1=Backup Complete</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_cancel_backup" var2="1" />
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="set">tw_complete_text1=Backup Cancelled</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="restore">
+ <object type="template" name="header" />
+
+ <object type="button" style="fillbutton">
+ <placement x="%col2_x%" y="%zipstorage_text_y%" w="%fileselector_folderonly_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%col2_x%" y="%fileselector_install_y%" w="%fileselector_folderonly_width%" h="%fileselector_install_height%" />
+ <text>Select Package to Restore:</text>
+ <filter folders="1" files="0" nav="0" />
+ <path name="tw_backups_folder" />
+ <data name="tw_restore" default="" />
+ <selection name="tw_restore_name" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <condition var1="tw_restore" op="modified" />
+ <actions>
+ <action function="readBackup"></action>
+ <action function="page">restore_read</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="restore_read">
+ <object type="action">
+ <condition var1="tw_restore_encrypted" var2="1" />
+ <actions>
+ <action function="set">tw_password_fail=0</action>
+ <action function="page">restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_restore_encrypted" var2="0" />
+ <actions>
+ <action function="page">restore_select</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="restore_decrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Backup encrypted. Please enter your password:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_restore_display%</text>
+ <data name="tw_restore_password" mask="*" maskvariable="tw_restore_display" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <actions>
+ <action function="page">try_restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Password Failed, Please Try Again</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">restore</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%cancel_button_y%" />
+ <text>Delete</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; rm -rf &quot;%tw_restore_name%&quot;</action>
+ <action function="set">tw_text1=Delete Backup? %tw_restore_name%</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Deleting Backup...</action>
+ <action function="set">tw_complete_text1=Backup Delete Complete</action>
+ <action function="set">tw_slider_text=Swipe to Delete</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="try_restore_decrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Trying Decryption with Your Password</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="decrypt_backup"></action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_password_fail=1</action>
+ <action function="page">restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">restore_select</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="restore_select">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Package to Restore: %tw_restore_name%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Package Date: %tw_restore_file_date%</text>
+ </object>
+
+ <object type="partitionlist">
+ <placement x="%backup_list_x%" y="%restore_list_y%" w="%backup_list_width%" h="%restore_list_height%" />
+ <text>Select Partitions to Restore:</text>
+ <data name="tw_restore_list" selectedlist="tw_restore_selected" />
+ <listtype name="restore" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col3_x%" y="%nandcheck_row6%" />
+ <text>Enable MD5 checking of backup files</text>
+ <data variable="tw_skip_md5_check" />
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%row1_y%" />
+ <text>Rename Backup</text>
+ <actions>
+ <action function="set">tw_backup_rename=</action>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">renamebackup</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row1_y%" />
+ <text>Delete Backup</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; rm -rf &quot;%tw_restore_name%&quot;</action>
+ <action function="set">tw_text1=Delete Backup? %tw_restore_name%</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Deleting Backup...</action>
+ <action function="set">tw_complete_text1=Backup Delete Complete</action>
+ <action function="set">tw_slider_text=Swipe to Delete</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Restore</text>
+ <action function="page">restore_run</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="renamebackup">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter a New Backup Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_rename%</text>
+ <data name="tw_backup_rename" />
+ <restrict minlen="1" maxlen="64" allow=" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_.{}[]" />
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; mv &quot;%tw_restore_name%&quot; &quot;%tw_backup_rename%&quot;</action>
+ <action function="set">tw_text1=Rename Backup?</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Renaming Backup...</action>
+ <action function="set">tw_complete_text1=Backup Rename Complete</action>
+ <action function="set">tw_slider_text=Swipe to Rename</action>
+ <action function="set">tw_filecheck=%tw_backups_folder%/%tw_backup_rename%</action>
+ <action function="set">tw_existpage=renamebackup</action>
+ <action function="set">tw_notexistpage=confirm_action</action>
+ <action function="page">filecheck</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_fileexists" var2="1" />
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <font resource="font" color="%text_fail_color%" />
+ <text>A backup with that name already exists!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <action function="page">restore_select</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore_select</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="restore_run">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_operation% %tw_partition%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_size_progress%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="set">tw_back=restore_select</action>
+ <action function="set">tw_complete_text1=Restore Complete</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <action function="nandroid">restore</action>
+ </object>
+ </page>
+
+ <page name="settings">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Settings</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>Zip file signature verification?</text>
+ <data variable="tw_signed_zip_verify" />>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Use rm -rf instead of formatting?</text>
+ <data variable="tw_rm_rf" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Skip MD5 generation on backups</text>
+ <data variable="tw_skip_md5_generate" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>Enable MD5 checking of backup files</text>
+ <data variable="tw_skip_md5_check" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row6_text_y%" />
+ <text>Use 24-hour clock</text>
+ <data variable="tw_military_time" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row7_text_y%" />
+ <text>Simulate most actions for theme testing</text>
+ <data variable="tw_simulate_actions" />
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_simulate_actions" var2="1" />
+ <placement x="%col1_x%" y="%row8_text_y%" />
+ <text>Simulate failure for actions</text>
+ <data variable="tw_simulate_fail" />
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Time Zone</text>
+ <action function="page">timezone</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Restore Defaults</text>
+ <action function="restoredefaultsettings"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row2_y%" />
+ <text>Vibration Duration</text>
+ <action function="page">Vibrate</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%row2_y%" />
+ <text>Screen</text>
+ <action function="page">screen</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="timezone">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Select Time Zone</text>
+ </object>
+
+ <object type="listbox" style="scrolllist">
+ <placement x="%listbox_x%" y="%listbox_y%" w="%listbox_width%" h="%listbox_tz_height%" />
+ <text>Select Time Zone:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_time_zone_guisel" />
+ <listitem name="(UTC -11) Samoa, Midway Island">BST11;BDT</listitem>
+ <listitem name="(UTC -10) Hawaii">HST10;HDT</listitem>
+ <listitem name="(UTC -9) Alaska">AST9;ADT</listitem>
+ <listitem name="(UTC -8) Pacific Time">PST8;PDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -7) Mountain Time">MST7;MDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -6) Central Time">CST6;CDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -5) Eastern Time">EST5;EDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -4) Atlantic Time">AST4;ADT</listitem>
+ <listitem name="(UTC -3) Brazil, Buenos Aires">GRNLNDST3;GRNLNDDT</listitem>
+ <listitem name="(UTC -2) Mid-Atlantic">FALKST2;FALKDT</listitem>
+ <listitem name="(UTC -1) Azores, Cape Verde">AZOREST1;AZOREDT</listitem>
+ <listitem name="(UTC 0) London, Dublin, Lisbon">GMT0;BST,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +1) Berlin, Brussels, Paris">CET-1;CEST,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +2) Athens, Istanbul, South Africa">WET-2;WET,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +3) Moscow, Baghdad">SAUST-3;SAUDT</listitem>
+ <listitem name="(UTC +4) Abu Dhabi, Tbilisi, Muscat">WST-4;WDT</listitem>
+ <listitem name="(UTC +5) Yekaterinburg, Islamabad">PAKST-5;PAKDT</listitem>
+ <listitem name="(UTC +6) Almaty, Dhaka, Colombo">TASHST-6;TASHDT</listitem>
+ <listitem name="(UTC +7) Bangkok, Hanoi, Jakarta">THAIST-7;THAIDT</listitem>
+ <listitem name="(UTC +8) Beijing, Singapore, Hong Kong">TAIST-8;TAIDT</listitem>
+ <listitem name="(UTC +9) Tokyo, Seoul, Yakutsk">JST-9;JSTDT</listitem>
+ <listitem name="(UTC +10) Eastern Australia, Guam">EET-10;EETDT</listitem>
+ <listitem name="(UTC +11) Vladivostok, Solomon Islands">MET-11;METDT</listitem>
+ <listitem name="(UTC +12) Auckland, Wellington, Fiji">NZST-12;NZDT</listitem>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_medium_x%" y="%row11_text_y%" />
+ <text>Do you use daylight savings time (DST)?</text>
+ <data variable="tw_time_zone_guidst" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row13_text_y%" placement="5" />
+ <text>Offset (usually 0): %tw_time_zone_guioffset%</text>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col1_medium_x%" y="%row_offsetmedium_y%" />
+ <text>0</text>
+ <action function="set">tw_time_zone_guioffset=0</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col2_medium_x%" y="%row_offsetmedium_y%" />
+ <text>15</text>
+ <action function="set">tw_time_zone_guioffset=15</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col3_medium_x%" y="%row_offsetmedium_y%" />
+ <text>30</text>
+ <action function="set">tw_time_zone_guioffset=30</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col4_medium_x%" y="%row_offsetmedium_y%" />
+ <text>45</text>
+ <action function="set">tw_time_zone_guioffset=45</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%row2_y%" />
+ <text>Set Time Zone</text>
+ <action function="setguitimezone"></action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row17_text_y%" placement="5" />
+ <text>Current Time Zone: %tw_time_zone%</text>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="screen">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Screen Settings</text>
+ </object>
+
+ <object type="button">
+ <placement x="%slidervalue_x%" y="%row3_text_y%" />
+ <condition var1="tw_screen_timeout_secs" op="=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ <text>Enable screen timeout.</text>
+ <image resource="checkbox_false" />
+ <action function="set">tw_screen_timeout_secs=60</action>
+ </object>
+
+ <object type="button">
+ <placement x="%slidervalue_x%" y="%row3_text_y%" />
+ <condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ <text>Enable screen timeout.</text>
+ <image resource="checkbox_true" />
+ <action function="set">tw_screen_timeout_secs=0</action>
+ </object>
+
+ <object type="slidervalue">
+ <conditions>
+ <condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ </conditions>
+ <placement x="slidervalue_x" y="%row5_text_y%" w="%slidervalue_w%" />
+ <text>Screen timeout in seconds:</text>
+ <data variable="tw_screen_timeout_secs" min="15" max="300" />
+ </object>
+
+ <object type="slidervalue">
+ <condition var1="tw_has_brightnesss_file" var2="1" />
+ <placement x="slidervalue_x" y="%row12_text_y%" w="%slidervalue_w%" />
+ <text>Brightness: %tw_brightness_pct%%</text>
+ <data variable="tw_brightness_pct" min="10" max="100" />
+ <actions>
+ <action function="set">tw_brightness=%tw_brightness_max%</action>
+ <action function="compute">tw_brightness*%tw_brightness_pct%</action>
+ <action function="compute">tw_brightness/100</action>
+ <action function="setbrightness">%tw_brightness%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="Vibrate">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Vibration Settings :</text>
+ </object>
+
+ <object type="slidervalue">
+ <placement x="slidervalue_x" y="%row3_text_y%" w="%slidervalue_w%" />
+ <text>Button Vibration:</text>
+ <data variable="tw_button_vibrate" min="0" max="300" />
+ <colors line="%slidervalue_line_clr%" slider="%slidervalue_slider_clr%" />
+ </object>
+
+ <object type="slidervalue">
+ <placement x="slidervalue_x" y="%row7_text_y%" w="%slidervalue_w%" />
+ <text>Keyboard Vibration:</text>
+ <data variable="tw_keyboard_vibrate" min="0" max="300" />
+ <colors line="%slidervalue_line_clr%" slider="%slidervalue_slider_clr%" />
+ </object>
+
+ <object type="slidervalue">
+ <placement x="slidervalue_x" y="%row11_text_y%" w="%slidervalue_w%" />
+ <text>Action Vibration:</text>
+ <data variable="tw_action_vibrate" min="0" max="500" />
+ <colors line="%slidervalue_line_clr%" slider="%slidervalue_slider_clr%" />
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="advanced">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Advanced</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Copy Log to SD</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=copylog</action>
+ <action function="set">tw_text1=Copy Log to SD Card?</action>
+ <action function="set">tw_action_text1=Copying Log to SD Card...</action>
+ <action function="set">tw_complete_text1=Log Copy Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Fix Permissions</text>
+ <action function="page">fixperms</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row1_y%" />
+ <text>Terminal Command</text>
+ <action function="page">terminalfolder</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%row1_y%" />
+ <text>ADB Sideload</text>
+ <action function="page">sideload</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_allow_partition_sdcard" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Partition SD Card</text>
+ <action function="page">partsdcard</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>File Manager</text>
+ <action function="page">filemanagerlist</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row2_y%" />
+ <text>Reload Theme</text>
+ <action function="reload"></action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_show_dumlock" var2="1" />
+ <placement x="%col4_x%" y="%row2_y%" />
+ <text>HTC Dumlock</text>
+ <action function="page">htcdumlock</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="partsdcard">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Partition SD Card</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_sdext_x%" y="%row1_sdext_y%" />
+ <text></text>
+ <image resource="minus_button" />
+ <action function="addsubtract">tw_sdext_size-128</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_sdext_x%" y="%row1_sdext_y%" />
+ <text></text>
+ <image resource="plus_button" />
+ <action function="addsubtract">tw_sdext_size+128</action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row_extsize_y%" placement="5" />
+ <text>EXT Size: %tw_sdext_size%</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_sdext_x%" y="%row2_sdext_y%" />
+ <text></text>
+ <image resource="minus_button" />
+ <action function="addsubtract">tw_swap_size-32</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_sdext_x%" y="%row2_sdext_y%" />
+ <text></text>
+ <image resource="plus_button" />
+ <action function="addsubtract">tw_swap_size+32</action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row_swapsize_y%" placement="5" />
+ <text>Swap Size: %tw_swap_size%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row8_text_y%" placement="5" />
+ <text>File system: %tw_sdpart_file_system%</text>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col2_medium_x%" y="%row4_medium_y%" />
+ <text>EXT3</text>
+ <action function="set">tw_sdpart_file_system=ext3</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <condition var1="tw_sdext_disable_ext4" var2="0" />
+ <placement x="%col3_medium_x%" y="%row4_medium_y%" />
+ <text>EXT4</text>
+ <action function="set">tw_sdpart_file_system=ext4</action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row12_text_y%" placement="5" />
+ <text>You will lose all files on your SD card!</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row13_text_y%" placement="5" />
+ <text>This action cannot be undone!</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Confirm Partition</text>
+ <actions>
+ <action function="set">tw_back=partsdcard</action>
+ <action function="set">tw_action=partitionsd</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=set</action>
+ <action function="set">tw_action2_param=tw_zip_location=/sdcard</action>
+ <action function="set">tw_action_text1=Partitioning SD Card...</action>
+ <action function="set">tw_action_text2=This will take a few minutes.</action>
+ <action function="set">tw_complete_text1=Partitioning Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+
+ <page name="htcdumlock">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>HTC Dumlock</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Restore Original Boot</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=htcdumlockrestoreboot</action>
+ <action function="set">tw_text1=Restore original boot image?</action>
+ <action function="set">tw_action_text1=Restoring Original Boot...</action>
+ <action function="set">tw_complete_text1=Restore Original Boot Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Reflash Recovery->Boot</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=htcdumlockreflashrecovery</action>
+ <action function="set">tw_text1=Reflash recovery to boot?</action>
+ <action function="set">tw_action_text1=Flashing recovery to boot...</action>
+ <action function="set">tw_complete_text1=Recovery Flash to Boot Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Install HTC Dumlock</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=installhtcdumlock</action>
+ <action function="set">tw_text1=Install HTC dumlock files to ROM?</action>
+ <action function="set">tw_action_text1=Installing HTC Dumlock...</action>
+ <action function="set">tw_complete_text1=HTC Dumlock Install Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="lock">
+ <background color="#000000A0" />
+
+ <object type="image">
+ <image resource="unlock-icon" />
+ <placement x="%center_x%" y="%lock_y%" placement="4" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Unlock</text>
+ <action function="overlay"></action>
+ </object>
+ </page>
+
+
+ <page name="filemanagerlist">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>File Manager: Select a File or Folder</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_folder_x%" y="%fileselector_install_y%" w="%fileselector_folder_width%" h="%fileselector_install_height%" />
+ <text>Folders:</text>
+ <filter folders="1" files="0" />
+ <path name="tw_file_location1" default="/sdcard" />
+ <data name="select" />
+ <selection name="tw_selection1" />
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_file_x%" y="%fileselector_install_y%" w="%fileselector_file_width%" h="%fileselector_install_height%" />
+ <text>%tw_file_location1%</text>
+ <filter folders="0" files="1" />
+ <path name="tw_file_location1" default="/" />
+ <data name="tw_filename1" />
+ <selection name="tw_selection1" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <actions>
+ <action function="set">tw_fm_type=File</action>
+ <action function="set">tw_fm_isfolder=0</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_filename1" op="modified" />
+ <actions>
+ <action function="page">filemanageroptions</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select Folder</text>
+ <actions>
+ <action function="set">tw_filename1=tw_file_location1</action>
+ <action function="set">tw_fm_isfolder=1</action>
+ <action function="set">tw_fm_type=Folder</action>
+ <action function="page">filemanageroptions</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanageroptions">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>%tw_fm_type% Selected:</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>%tw_filename1%</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="0" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Copy File</text>
+ <actions>
+ <action function="set">tw_filemanager_command=cp</action>
+ <action function="set">tw_fm_text1=Copying</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Copy Folder</text>
+ <actions>
+ <action function="set">tw_filemanager_command=cd &quot;%tw_file_location1%&quot; &amp;&amp; cd .. &amp;&amp; cp -R</action>
+ <action function="set">tw_fm_text1=Copying</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Move</text>
+ <actions>
+ <action function="set">tw_filemanager_command=mv</action>
+ <action function="set">tw_fm_text1=Moving</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col3_x%" y="%row2_y%" />
+ <text>chmod 755</text>
+ <actions>
+ <action function="set">tw_filemanager_command=chmod 755</action>
+ <action function="set">tw_fm_text1=chmod 755</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%row2_y%" />
+ <text>chmod</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=0000</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerchmod</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Delete</text>
+ <actions>
+ <action function="set">tw_filemanager_command=rm -rf</action>
+ <action function="set">tw_fm_text1=Deleting</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="0" />
+ <placement x="%col4_x%" y="%row1_y%" />
+ <text>Rename File</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=tw_selection1</action>
+ <action function="set">tw_fm_text1=Renaming</action>
+ <action function="set">tw_filemanager_command=mv</action>
+ <action function="page">filemanagerrenamefile</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="1" />
+ <placement x="%col4_x%" y="%row1_y%" />
+ <text>Rename Folder</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=tw_selection1</action>
+ <action function="set">tw_fm_text1=Renaming</action>
+ <action function="set">tw_filemanager_command=cd &quot;%tw_file_location1%&quot; &amp;&amp; cd .. &amp;&amp; mv</action>
+ <action function="page">filemanagerrenamefolder</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanagerlist</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="choosedestinationfolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>Browse to Destination Folder &amp; Press Select</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%col2_x%" y="%fileselector_install_y%" w="%fileselector_folderonly_width%" h="%fileselector_install_height%" />
+ <text>%tw_file_location2%</text>
+ <background color="%fileselector_background%" />
+ <filter folders="1" files="0" />
+ <path name="tw_file_location2" default="/sdcard" />
+ <data name="tw_filename2" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="button">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select Folder</text>
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=%tw_file_location2%</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerrenamefile">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <font resource="font" color="%text_color%" />
+ <text>Please Enter a New %tw_fm_type% Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="1" maxlen="128" />
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=&quot;%tw_file_location1%/%tw_filemanager_rename%&quot;</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerrenamefolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter a New %tw_fm_type% Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="1" maxlen="128" />
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=%tw_filemanager_rename%</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerchmod">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter New Permissions</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="3" maxlen="4" allow="0123456789" />
+ <actions>
+ <action function="set">tw_filemanager_command=chmod %tw_filemanager_rename%</action>
+ <action function="set">tw_fm_text1=chmod %tw_filemanager_rename%</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerconfirm">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>%tw_fm_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>%tw_filename1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5"/>
+ <text>%tw_fm_text2%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5"/>
+ <text>%tw_fm_text3%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row10_text_y%" placement="5"/>
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="slider">
+ <action function="page">filemanageracction</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">%tw_back%</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanageracction">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_fm_text1%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_back=filemanagerlist</action>
+ <action function="set">tw_complete_text1=File Operation Complete</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_complete_text1=File Operation Complete</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_include_text3" var2="0" />
+ <actions>
+ <action function="cmd">%tw_filemanager_command% &quot;%tw_filename1%&quot;</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_include_text3" var2="1" />
+ <actions>
+ <action function="cmd">%tw_filemanager_command% &quot;%tw_filename1%&quot; &quot;%tw_fm_text3%&quot;</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="decrypt">
+ <object type="template" name="header" />
+
+ <object type="action">
+ <condition var1="tw_crypto_pwtype" var2="2" />
+ <action function="page">decrypt_pattern</action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter Your Password</text>
+ </object>
+
+ <object type="input">
+ <placement x="%input_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_crypto_display%</text>
+ <data name="tw_crypto_password" mask="*" maskvariable="tw_crypto_display" />
+ <restrict minlen="1" maxlen="254" />
+ <actions>
+ <action function="page">trydecrypt</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Password Failed, Please Try Again</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="decrypt_pattern">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter Your Pattern</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Pattern Failed, Please Try Again</text>
+ </object>
+
+ <object type="patternpassword">
+ <placement x="%pattern_x%" y="%pattern_y%" w="%pattern_width%" h="%pattern_width%" />
+ <dot color="%pattern_dot_color%" activecolor="%pattern_dot_color_active%" radius="%pattern_dot_radius%" />
+ <line color="%pattern_line_color%" width="%pattern_line_width%" />
+ <data name="tw_crypto_password"/>
+ <action function="page">trydecrypt</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col4_x%" y="%cancel_button_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="trydecrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Trying Decryption with Your Password</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="decrypt"></action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_password_fail=1</action>
+ <action function="page">decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="terminalfolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>Browse to Starting Folder</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%col2_x%" y="%fileselector_install_y%" w="%fileselector_folderonly_width%" h="%fileselector_install_height%" />
+ <text>%tw_terminal_location%</text>
+ <filter folders="1" files="0" />
+ <path name="tw_terminal_location" default="/" />
+ <data name="tw_terminal" />
+ <selection name="tw_terminal_selection" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="button">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select Folder</text>
+ <actions>
+ <action function="page">terminalcommand</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="terminalcommand">
+ <background color="#000000FF" />
+
+ <object type="console">
+ <placement x="%console_x%" y="%terminal_console_y%" w="%console_width%" h="%terminal_console_height%" />
+ </object>
+
+ <object type="text">
+ <placement x="%input_x%" y="%terminal_text_y%" placement="0" />
+ <text>Starting Path: %tw_terminal_location%</text>
+ </object>
+
+ <object type="input">
+ <condition var1="tw_terminal_state" var2="0" />
+ <placement x="%input_x%" y="%terminal_text_y%" w="%terminal_input_width%" h="%input_height%" placement="0" />
+ <text>%tw_terminal_command%</text>
+ <font resource="fixed" color="%text_color%" />
+ <data name="tw_terminal_command" />
+ <restrict minlen="1" />
+ <action function="terminalcommand">%tw_terminal_command%</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <condition var1="tw_terminal_state" var2="1" />
+ <placement x="%filemanager_select_x%" y="%terminal_button_y%" />
+ <text>KILL</text>
+ <action function="killterminal"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%home_button_x%" y="%terminal_button_y%" />
+ <text></text>
+ <image resource="home_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">home</action>
+ </object>
+
+ <object type="button">
+ <placement x="%back_button_x%" y="%terminal_button_y%" />
+ <text></text>
+ <image resource="back_icon" />
+ <condition var1="tw_busy" var2="0" />
+ <action function="key">back</action>
+ </object>
+
+ <object type="action">
+ <touch key="power" />
+ <action function="overlay">lock</action>
+ </object>
+
+ <object type="action">
+ <touch key="power+voldown" />
+ <action function="screenshot" />
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">terminalfolder</action>
+ </object>
+ </page>
+
+ <page name="sideload">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>ADB Sideload</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Wipe Dalvik Cache.</text>
+ <data variable="tw_wipe_dalvik" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Wipe Cache.</text>
+ <data variable="tw_wipe_cache" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Start Sideload</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=adbsideload</action>
+ <action function="set">tw_action_text1=ADB Sideload</action>
+ <action function="set">tw_action_text2=Usage: adb sideload filename.zip</action>
+ <action function="set">tw_complete_text1=ADB Sideload Complete</action>
+ <action function="set">tw_has_cancel=1</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="set">tw_cancel_action=adbsideloadcancel</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="fixperms">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>Fix Permissions</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col2_x%" y="%row2_text_y%" />
+ <text>Note: Fixing permissions is rarely needed.</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col2_x%" y="%row3_text_y%" />
+ <text>Also fix SELinux contexts</text>
+ <data variable="tw_fixperms_restorecon" />
+ </object>
+
+ <object type="text">
+ <placement x="%col2_x%" y="%row4_text_y%" />
+ <text>Fixing SELinux contexts may cause your device to not boot properly.</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Fix Permissions</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=fixpermissions</action>
+ <action function="set">tw_action_text1=Fixing Permissions...</action>
+ <action function="set">tw_complete_text1=Fix Permissions Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="installsu">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>Install SuperSU?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>Your device does not appear to be rooted.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5"/>
+ <text>Install SuperSU now? This will root your device.</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_medium_y%" />
+ <text>Do Not Install</text>
+ <action function="set">tw_page_done=1</action>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Install</text>
+ <actions>
+ <action function="set">tw_action=installsu</action>
+ <action function="set">tw_action_text1=Installing SuperSU</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="page">singleaction_page</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="system_readonly">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Keep System Read Only?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>TWRP can leave your system partition unmodified to make it easier for you to take official updates.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>TWRP will be unable to prevent the stock ROM from replacing TWRP and will not offer to root your device.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Installing zips or performing adb operations may still modify the system partition.</text>
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_is_encrypted" var2="0" />
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>Never show this screen during boot again</text>
+ <data variable="tw_never_show_system_ro_page" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row7_text_y%" />
+ <text>Keep Read Only</text>
+ <actions>
+ <action function="mountsystemtoggle">1</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Allow Modifications</text>
+ <actions>
+ <action function="mountsystemtoggle">0</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+ </pages>
+</recovery>
diff --git a/gui/devices/portrait/res/portrait.xml b/gui/devices/portrait/res/portrait.xml
new file mode 100644
index 000000000..969044c19
--- /dev/null
+++ b/gui/devices/portrait/res/portrait.xml
@@ -0,0 +1,3740 @@
+<?xml version="1.0"?>
+
+<recovery>
+ <styles>
+ <style name="buttontext">
+ <highlight color="%highlight_color%" />
+ <font resource="font" color="%button_text_color%" />
+ </style>
+
+ <style name="button">
+ <style name="buttontext" />
+ <image resource="main_button" />
+ </style>
+
+ <style name="mediumbutton">
+ <style name="buttontext" />
+ <image resource="medium_button" />
+ </style>
+
+ <style name="fillbutton">
+ <style name="buttontext" />
+ <fill color="%button_fill_color%" />
+ </style>
+
+ <style name="rebootsystem">
+ <condition var1="tw_reboot_system" var2="1" />
+ <style name="button" />
+ <text>Reboot System</text>
+ <actions>
+ <action function="set">tw_back=main2</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=system</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_text3=</action>
+ <action function="set">tw_text4=</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </style>
+
+ <style name="scrolllist">
+ <highlight color="%fileselector_highlight_color%" />
+ <header background="%fileselector_header_background%" textcolor="%fileselector_header_textcolor%" separatorcolor="%fileselector_header_separatorcolor%" separatorheight="%fileselector_header_separatorheight%" />
+ <fastscroll linecolor="%fastscroll_linecolor%" rectcolor="%fastscroll_rectcolor%" w="%fastscroll_w%" linew="%fastscroll_linew%" rectw="%fastscroll_rectw%" recth="%fastscroll_recth%" />
+ <separator color="%fileselector_separatorcolor%" height="%fileselector_separatorheight%" />
+ <background color="%fileselector_background%" />
+ <font resource="filelist" spacing="%fileselector_spacing%" color="%text_color%" highlightcolor="%fileselector_highlight_font_color%" />
+ </style>
+
+ <style name="fileselector">
+ <style name="scrolllist" />
+ <icon folder="folder_icon" file="file_icon" />
+ <sort name="tw_gui_sort_order" />
+ </style>
+
+ <style name="partitionlist">
+ <style name="scrolllist" />
+ <icon selected="checkbox_true" unselected="checkbox_false" />
+ </style>
+
+ <style name="text">
+ <font resource="font" color="%text_color%" />
+ </style>
+
+ <style name="checkbox">
+ <font resource="font" color="%text_color%" />
+ <image checked="checkbox_true" unchecked="checkbox_false" />
+ </style>
+
+ <style name="slider">
+ <text>Swipe to Confirm</text>
+ <font resource="font" color="%text_color%" />
+ <placement x="%center_x%" y="%slider_y%" placement="5" />
+ <resource base="slider" used="slider-used" touch="slider-touch" />
+ </style>
+
+ <style name="console">
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ <fastscroll linecolor="%fastscroll_linecolor%" rectcolor="%fastscroll_rectcolor%" w="%fastscroll_w%" linew="%fastscroll_linew%" rectw="%fastscroll_rectw%" recth="%fastscroll_recth%" />
+ </style>
+
+ <style name="input">
+ <background color="%input_background_color%" />
+ <cursor color="%input_cursor_color%" hasfocus="1" width="%input_cursor_width%" />
+ <font resource="font" color="%text_color%" />
+ </style>
+
+ <style name="slidervalue">
+ <font resource="font" color="%text_color%" />
+ <colors line="%slidervalue_line_clr%" slider="%slidervalue_slider_clr%" />
+ <dimensions lineh="%slidervalue_lineh%" linepadding="%slidervalue_padding%" sliderw="%slidervalue_sliderw%" sliderh="%slidervalue_sliderh%" />
+ </style>
+ </styles>
+
+ <pages>
+ <page name="main">
+ <object type="action">
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="main2">
+ <object type="template" name="header" />
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Install</text>
+ <actions>
+ <action function="queueclear"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Wipe</text>
+ <action function="page">wipe</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Backup</text>
+ <action function="page">backup</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Restore</text>
+ <action function="page">restore</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Mount</text>
+ <action function="page">mount</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>Settings</text>
+ <action function="page">settings</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Advanced</text>
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Reboot</text>
+ <action function="page">reboot</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="install">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Select Zip to Install</text>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%row1_text_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=install</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row3_text_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_zip_location%</text>
+ <filter extn=".zip" folders="1" files="1" />
+ <path name="tw_zip_location" default="/sdcard" />
+ <data name="tw_filename" />
+ <selection name="tw_file" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Images...</text>
+ <actions>
+ <action function="page">install_image</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_filename" op="modified" />
+ <actions>
+ <action function="queuezip"></action>
+ <action function="page">flash_confirm</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="flash_confirm">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>This operation may install incompatible</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>software and render your device unusable.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>Folder:</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%"/>
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>%tw_zip_location%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>File to flash:</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%"/>
+ <placement x="%center_x%" y="%row6_text_y%" placement="5" />
+ <text>%tw_file%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row7_text_y%" placement="5" />
+ <text>Press back to cancel adding this zip.</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row8_text_y%" />
+ <text>Zip file signature verification.</text>
+ <data variable="tw_signed_zip_verify" />
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_has_injecttwrp" var2="1" />
+ <placement x="%col1_x%" y="%row10_text_y%" />
+ <text>Inject TWRP after install.</text>
+ <data variable="tw_inject_after_zip" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row11_text_y%" placement="5" />
+ <text>File %tw_zip_queue_count% of max of 10</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Confirm Flash</text>
+ <action function="flash">flash_zip</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_zip_queue_count" op="!=" var2="10"></condition>
+ <placement x="%col1_x%" y="%row_queue_y%" />
+ <text>Add More Zips</text>
+ <action function="page">install</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row_queue_y%" />
+ <text>Clear Zip Queue</text>
+ <actions>
+ <action function="queueclear"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="cancelzip"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="flash_zip">
+ <object type="template" name="header" />
+
+ <object type="console">
+ <placement x="%console_x%" y="%row1_y%" w="%console_width%" h="%console_install_height%" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row17_text_y%" placement="5" />
+ <text>Flashing file %tw_zip_index% of %tw_zip_queue_count%</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%"/>
+ <placement x="%center_x%" y="%row18_text_y%" placement="5" />
+ <text>%tw_filename%</text>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <action function="page">flash_done</action>
+ </object>
+ </page>
+
+ <page name="flash_done">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Zip Install Complete</text>
+ </object>
+
+ <object type="console">
+ <placement x="%console_x%" y="%row1_y%" w="%console_width%" h="%console_installdone_height%" />
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Wipe cache/dalvik</text>
+ <actions>
+ <action function="set">tw_back=flash_done</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=/cache</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=wipe</action>
+ <action function="set">tw_action2_param=dalvik</action>
+ <action function="set">tw_text1=Wipe Cache &amp; Dalvik?</action>
+ <action function="set">tw_action_text1=Wiping Cache &amp; Dalvik...</action>
+ <action function="set">tw_complete_text1=Cache &amp; Dalvik Wipe Complete</action>
+ <action function="set">tw_slider_text=Swipe to Wipe</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <style name="rebootsystem" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row3_y%" />
+ <text>Home</text>
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%center_x%" y="%zip_status_y%" placement="5" />
+ <text>Failed</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" var2="0" />
+ <font resource="font" color="%text_success_color%"/>
+ <placement x="%center_x%" y="%zip_status_y%" placement="5" />
+ <text>Successful</text>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=install</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="install_image">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Select Image to Install</text>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%row1_text_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=install_image</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row3_text_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_zip_location%</text>
+ <filter extn=".img" folders="1" files="1" />
+ <path name="tw_zip_location" default="/sdcard" />
+ <data name="tw_filename" />
+ <selection name="tw_file" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Zips...</text>
+ <actions>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_filename" op="modified" />
+ <action function="page">flashimage_confirm</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">install</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="flashimage_confirm">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%flash_list_height%" />
+ <text>Select Partition to Flash Image:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_flash_partition" />
+ <listtype name="flashimg" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row8_text_y%" placement="5" />
+ <text>Folder:</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%"/>
+ <placement x="%center_x%" y="%row9_text_y%" placement="5" />
+ <text>%tw_zip_location%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row10_text_y%" placement="5" />
+ <text>File to flash:</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%"/>
+ <placement x="%center_x%" y="%row11_text_y%" placement="5" />
+ <text>%tw_file%</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Confirm Flash</text>
+ <actions>
+ <action function="set">tw_back=flashimage_confirm</action>
+ <action function="set">tw_action=flashimage</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_action_text1=Flashing Image...</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_complete_text1=Image Flashed</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=install_image</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="clear_vars">
+ <object type="action">
+ <action function="set">tw_operation_state=0</action>
+ <action function="set">tw_text1=</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_text3=</action>
+ <action function="set">tw_text4=</action>
+ <action function="set">tw_action_text1=</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_action_param=</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_action2=</action>
+ <action function="set">tw_action2_param=</action>
+ <action function="set">tw_has_cancel=0</action>
+ <action function="set">tw_cancel_action=</action>
+ <action function="set">tw_cancel_param=</action>
+ <action function="set">tw_show_exclamation=0</action>
+ <action function="set">tw_show_reboot=0</action>
+ <action function="page">%tw_clear_destination%</action>
+ </object>
+ </page>
+
+ <page name="confirm_action">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_text2%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_text3%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>%tw_text4%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row15_text_y%" placement="5" />
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="slider">
+ <text>%tw_slider_text%</text>
+ <action function="page">action_page</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="action_page">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_action_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_action_text2%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="button" style="mediumbutton">
+ <condition var1="tw_has_cancel" var2="1" />
+ <placement x="%col_center_medium_x%" y="%row4_y%" />
+ <text>Cancel</text>
+ <action function="%tw_cancel_action%">%tw_cancel_param%</action>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="0" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="1" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ <action function="%tw_action2%">%tw_action2_param%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="singleaction_page">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_action_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_action_text2%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="0" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="1" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ <action function="%tw_action2%">%tw_action2_param%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="action_complete">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_complete_text1%</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Failed</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" var2="0" />
+ <font resource="font" color="%text_success_color%"/>
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Successful</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="button">
+ <condition var1="tw_show_reboot" var2="0" />
+ <placement x="%col_center_x%" y="%row4_y%" />
+ <text>Back</text>
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="button" style="rebootsystem">
+ <condition var1="tw_show_reboot" var2="1" />
+ <placement x="%col_center_x%" y="%row4_y%" />
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="filecheck">
+ <object type="action">
+ <action function="fileexists">%tw_filecheck%</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_fileexists=1</action>
+ <action function="page">%tw_existpage%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="1" />
+ </conditions>
+ <actions>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">%tw_notexistpage%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="rebootcheck">
+ <object type="action">
+ <condition var1="tw_backup_system_size" op="&gt;=" var2="%tw_min_system%" />
+ <action function="reboot">%tw_action_param%</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_backup_system_size" op="&lt;" var2="%tw_min_system%" />
+ <action function="page">confirm_action</action>
+ </object>
+ </page>
+
+ <page name="wipe">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Factory Reset</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Wipes Data, Cache, and Dalvik</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_has_data_media" var2="1" />
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>(not including internal storage)</text>
+ </object>
+
+ <object type="text">
+ <conditions>
+ <condition var1="tw_has_android_secure" var2="1" />
+ <condition var1="fileexists" var2="/and-sec" />
+ </conditions>
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Android Secure</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_has_sdext_partition" var2="1" />
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>SD-EXT</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row6_text_y%" placement="5" />
+ <text>Most of the time this is</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row7_text_y%" placement="5" />
+ <text>the only wipe that you need.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row16_text_y%" placement="5" />
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%wipe_button_y%" />
+ <text>Advanced Wipe</text>
+ <actions>
+ <action function="set">partitionlisterror=0</action>
+ <action function="page">advancedwipe</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_has_data_media" var2="1" />
+ <placement x="%col2_x%" y="%wipe_button_y%" />
+ <text>Format Data</text>
+ <actions>
+ <action function="page">formatdata</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_is_encrypted" var2="1" />
+ <condition var1="tw_has_data_media" var2="0" />
+ </conditions>
+ <placement x="%col2_x%" y="%wipe_button_y%" />
+ <text>Wipe Encryption</text>
+ <actions>
+ <action function="set">tw_back=wipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=DATAMEDIA</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Wipe Encryption from Data?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting Data...</action>
+ <action function="set">tw_complete_text1=Data Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Format Data</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Factory Reset</text>
+ <actions>
+ <action function="set">tw_back=wipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=data</action>
+ <action function="set">tw_action_text1=Factory Reset...</action>
+ <action function="set">tw_complete_text1=Factory Reset Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="advancedwipe">
+ <object type="template" name="header" />
+
+ <object type="action">
+ <action function="set">tw_wipe_list=</action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Wipe Menu</text>
+ </object>
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%wipe_list_height%" />
+ <text>Select Partitions to Wipe:</text>
+ <data name="tw_wipe_list" />
+ <listtype name="wipe" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Wipe</text>
+ <actions>
+ <action function="set">tw_back=advancedwipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=LIST</action>
+ <action function="set">tw_text1=Wipe Selected Partition(s)?</action>
+ <action function="set">tw_action_text1=Wiping Partition(s)...</action>
+ <action function="set">tw_complete_text1=Wipe Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%wipe_button_row1%" w="%button_fill_full_width%" h="%button_fill_half_height%" />
+ <text>Repair or Change File System</text>
+ <actions>
+ <action function="checkpartitionlist"></action>
+ <action function="page">checkpartitionlist</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <font resource="font" color="%text_fail_color%"/>
+ <condition var1="partitionlisterror" var2="1" />
+ <placement x="%center_x%" y="%wipe_button_row1%" placement="5" />
+ <text>Invalid partition selection</text>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">wipe</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="formatdata">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Format Data will wipe all of your apps,</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>backups, pictures, videos, media, and</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>removes encryption on internal storage.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>This cannot be undone. Press back to cancel.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Type yes to continue.</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row6_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_confirm_formatdata%</text>
+ <data name="tw_confirm_formatdata" />
+ <restrict minlen="3" maxlen="3" allow="yes" />
+ <action function="page">formatdata_confirm</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">wipe</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="formatdata_confirm">
+ <object type="action">
+ <condition var1="tw_confirm_formatdata" op="=" var2="yes" />
+ <actions>
+ <action function="set">tw_back=formatdata</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=DATAMEDIA</action>
+ <action function="set">tw_action_text1=Formatting Data...</action>
+ <action function="set">tw_complete_text1=Data Format Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_confirm_formatdata" op="!=" var2="yes" />
+ <action function="page">formatdata</action>
+ </object>
+ </page>
+
+ <page name="checkpartitionlist">
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=0</action>
+ <action function="getpartitiondetails"></action>
+ <action function="page">partitionoptions</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="!=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=1</action>
+ <action function="set">tw_wipe_list=</action>
+ <action function="page">advancedwipe</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="partitionoptions">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Partition Options for: %tw_partition_name%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Mount Point: %tw_partition_mount_point%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Current file system: %tw_partition_file_system%</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_is_present" op="!=" var2="0" />
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Present: Yes</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_is_present" op="=" var2="0" />
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Present: No</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_removable" op="!=" var2="0" />
+ <placement x="%col2_x%" y="%row3_text_y%" />
+ <text>Removable: Yes</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_removable" op="=" var2="0" />
+ <placement x="%col2_x%" y="%row3_text_y%" />
+ <text>Removable: No</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Size: %tw_partition_size%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col2_x%" y="%row4_text_y%" />
+ <text>Used: %tw_partition_used%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>Free: %tw_partition_free%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col2_x%" y="%row5_text_y%" />
+ <text>Backup Size: %tw_partition_backup_size%MB</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_can_resize" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Resize</text>
+ <actions>
+ <action function="set">tw_back=partitionoptions</action>
+ <action function="set">tw_action=resize</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=getpartitiondetails</action>
+ <action function="set">tw_text1=Resize %tw_partition_name%?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Resizing...</action>
+ <action function="set">tw_complete_text1=Resize Complete</action>
+ <action function="set">tw_slider_text=Swipe to Resize</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_can_repair" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Repair</text>
+ <actions>
+ <action function="set">tw_back=partitionoptions</action>
+ <action function="set">tw_action=repair</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Repair %tw_partition_name%?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Repairing...</action>
+ <action function="set">tw_complete_text1=Repair Complete</action>
+ <action function="set">tw_slider_text=Swipe to Repair</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Change File System</text>
+ <action function="page">selectfilesystem</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advancedwipe</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="refreshfilesystem">
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=0</action>
+ <action function="getpartitiondetails"></action>
+ <action function="page">selectfilesystem</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="!=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=1</action>
+ <action function="set">tw_wipe_list=</action>
+ <action function="page">advancedwipe</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="selectfilesystem">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Change file system for: %tw_partition_name%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Mount Point: %tw_partition_mount_point%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Current file system: %tw_partition_file_system%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>Some ROMs or kernels may not support some</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>file systems. Proceed with caution!</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>EXT2</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext2</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT2?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>EXT3</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext3</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT3?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>EXT4</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext4</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT4?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_f2fs" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>F2FS</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=f2fs</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to F2FS?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_vfat" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>FAT</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=vfat</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to FAT?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_exfat" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>exFAT</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=exfat</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to exFAT?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">partitionoptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backup">
+ <object type="template" name="header" />
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%row1_header_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Backup Name: %tw_backup_name%</text>
+ <actions>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">backupname1</action>
+ </actions>
+ </object>
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row2_text_y%" w="%listbox_width%" h="%backup_list_height%" />
+ <text>Select Partitions to Back Up:</text>
+ <data name="tw_backup_list" />
+ <listtype name="backup" />
+ </object>
+
+ <object type="button" style="fillbutton">
+ <conditions>
+ <condition var1="tw_include_encrypted_backup" var2="1" />
+ <condition var1="tw_encrypt_backup" var2="0" />
+ </conditions>
+ <placement x="%col1_x%" y="%backup_button_row1%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>No Encryption</text>
+ <actions>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <conditions>
+ <condition var1="tw_include_encrypted_backup" var2="1" />
+ <condition var1="tw_encrypt_backup" var2="1" />
+ </conditions>
+ <placement x="%col1_x%" y="%backup_button_row1%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>Using Encryption</text>
+ <actions>
+ <action function="set">tw_password_not_match=0</action>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col2_x%" y="%backup_button_row1%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>Refresh Sizes</text>
+ <actions>
+ <action function="refreshsizes"></action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%backup_button_row2%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row15_text_y%" />
+ <text>Enable compression.</text>
+ <data variable="tw_use_compression" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row16_text_y%" />
+ <text>Skip MD5 generation during backup.</text>
+ <data variable="tw_skip_md5_generate" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row17_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <text>Disable Free Space Check.</text>
+ <data variable="tw_disable_free_space" />
+ <image checked="checkbox_true" unchecked="checkbox_false" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Back Up</text>
+ <action function="page">backup_run</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backupname1">
+ <object type="action">
+ <condition var1="tw_backup_name" op="=" var2="(Auto Generate)" />
+ <action function="generatebackupname"></action>
+ </object>
+
+ <object type="action">
+ <action function="page">backupname2</action>
+ </object>
+ </page>
+
+ <page name="backupname2">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter a Backup Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_name%</text>
+ <data name="tw_backup_name" />
+ <restrict minlen="1" maxlen="64" allow=" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_.{}[]" />
+ <actions>
+ <action function="set">tw_filecheck=%tw_backups_folder%/%tw_backup_name%</action>
+ <action function="set">tw_existpage=backupname2</action>
+ <action function="set">tw_notexistpage=backup</action>
+ <action function="page">filecheck</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_fileexists" var2="1" />
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <font resource="font" color="%text_fail_color%"/>
+ <text>A backup with that name already exists!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Append Date</text>
+ <action function="appenddatetobackupname"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backupencryption">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Encrypt your backup?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Please Enter A Password:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_encrypt_display%</text>
+ <data name="tw_backup_password" mask="*" maskvariable="tw_backup_encrypt_display" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <action function="page">backupencryption2</action>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_not_match" var2="1" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Passwords Do Not Match</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">backup</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backupencryption2">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Encrypt your backup?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Please Enter Password Again:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_encrypt_display2%</text>
+ <data name="tw_backup_password2" mask="*" maskvariable="tw_backup_encrypt_display2" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <actions>
+ <action function="page">checkbackuppassword</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">backup</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="checkbackuppassword">
+ <object type="action">
+ <condition var1="tw_backup_password2" var2="tw_backup_password" />
+ <actions>
+ <action function="set">tw_encrypt_backup=1</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_backup_password2" op="!=" var2="tw_backup_password" />
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_password_not_match=1</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="backup_run">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_operation% %tw_partition%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_file_progress%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_size_progress%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col_center_medium_x%" y="%row4_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="cancelbackup"></action>
+ </actions>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="nandroid">backup</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_cancel_backup" var2="0" />
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="set">tw_complete_text1=Backup Complete</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_cancel_backup" var2="1" />
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="set">tw_complete_text1=Backup Cancelled</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="restore">
+ <object type="template" name="header" />
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%row1_header_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row2_text_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>Select Package to Restore:</text>
+ <filter folders="1" files="0" nav="0" />
+ <path name="tw_backups_folder" />
+ <data name="tw_restore" default="" />
+ <selection name="tw_restore_name" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <condition var1="tw_restore" op="modified" />
+ <actions>
+ <action function="readBackup"></action>
+ <action function="page">restore_read</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="restore_read">
+ <object type="action">
+ <condition var1="tw_restore_encrypted" var2="1" />
+ <actions>
+ <action function="set">tw_password_fail=0</action>
+ <action function="page">restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_restore_encrypted" var2="0" />
+ <actions>
+ <action function="page">restore_select</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="restore_decrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Backup Encrypted</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Please Enter Your Password:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_restore_display%</text>
+ <data name="tw_restore_password" mask="*" maskvariable="tw_restore_display" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <actions>
+ <action function="page">try_restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Password Failed, Please Try Again</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">restore</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Delete</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; rm -rf &quot;%tw_restore_name%&quot;</action>
+ <action function="set">tw_text1=Delete Backup? %tw_restore_name%</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Deleting Backup...</action>
+ <action function="set">tw_complete_text1=Backup Delete Complete</action>
+ <action function="set">tw_slider_text=Swipe to Delete</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="try_restore_decrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Trying Decryption with Your Password</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="decrypt_backup"></action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_password_fail=1</action>
+ <action function="page">restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">restore_select</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="restore_select">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%backup_list_height%" />
+ <text>Restoring: %tw_restore_name%</text>
+ <data name="tw_restore_list" selectedlist="tw_restore_selected" />
+ <listtype name="restore" />
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%backup_button_row1%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>Rename Backup</text>
+ <actions>
+ <action function="set">tw_backup_rename=</action>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">renamebackup</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col2_x%" y="%backup_button_row1%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>Delete Backup</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; rm -rf &quot;%tw_restore_name%&quot;</action>
+ <action function="set">tw_text1=Delete Backup? %tw_restore_name%</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Deleting Backup...</action>
+ <action function="set">tw_complete_text1=Backup Delete Complete</action>
+ <action function="set">tw_slider_text=Swipe to Delete</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row15_text_y%" />
+ <text>Enable MD5 verification of backup files.</text>
+ <data variable="tw_skip_md5_check" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row16_text_y%" placement="5" />
+ <text>Package Date: %tw_restore_file_date%</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Restore</text>
+ <action function="page">restore_run</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="renamebackup">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter a New Backup Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_rename%</text>
+ <data name="tw_backup_rename" />
+ <restrict minlen="1" maxlen="64" allow=" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_.{}[]" />
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; mv &quot;%tw_restore_name%&quot; &quot;%tw_backup_rename%&quot;</action>
+ <action function="set">tw_text1=Rename Backup?</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Renaming Backup...</action>
+ <action function="set">tw_complete_text1=Backup Rename Complete</action>
+ <action function="set">tw_slider_text=Swipe to Rename</action>
+ <action function="set">tw_filecheck=%tw_backups_folder%/%tw_backup_rename%</action>
+ <action function="set">tw_existpage=renamebackup</action>
+ <action function="set">tw_notexistpage=confirm_action</action>
+ <action function="page">filecheck</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_fileexists" var2="1" />
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <font resource="font" color="%text_fail_color%"/>
+ <text>A backup with that name already exists!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <action function="page">restore_select</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore_select</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="restore_run">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_operation% %tw_partition%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_size_progress%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="set">tw_back=restore_select</action>
+ <action function="set">tw_complete_text1=Restore Complete</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <action function="nandroid">restore</action>
+ </object>
+ </page>
+
+ <page name="selectstorage">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%storage_list_height%" />
+ <text>Select Storage:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_storage_path" />
+ <listtype name="storage" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row4_y%" />
+ <text>OK</text>
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="mount">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%mount_list_height%" />
+ <text>Select Partitions to Mount:</text>
+ <listtype name="mount" />
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%mount_storage_row%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_has_usb_storage" var2="1" />
+ <placement x="%col1_x%" y="row4_y" />
+ <text>Mount USB Storage</text>
+ <action function="page">usb_mount</action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_has_mtp" var2="1" />
+ <condition var1="tw_mtp_enabled" var2="0" />
+ </conditions>
+ <placement x="%col2_x%" y="row4_y" />
+ <text>Enable MTP</text>
+ <action function="startmtp"></action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_has_mtp" var2="1" />
+ <condition var1="tw_mtp_enabled" var2="1" />
+ </conditions>
+ <placement x="%col2_x%" y="row4_y" />
+ <text>Disable MTP</text>
+ <action function="stopmtp"></action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_is_encrypted" var2="1" />
+ <condition var1="tw_is_decrypted" var2="0" />
+ </conditions>
+ <placement x="%col2_x%" y="row4_y" />
+ <text>Decrypt Data</text>
+ <action function="page">decrypt</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%system_ro_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_false" />
+ <action function="mountsystemtoggle">1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%system_ro_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="!=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_true" />
+ <actions>
+ <action function="set">tw_lifetime_writes=2</action>
+ <action function="page">system_readonly_check</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="usb_mount">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>USB Storage Mounted</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row1_text_y%" />
+ <text>Be sure to safely remove your device</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>from your computer before unmounting!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Unmount</text>
+ <action function="page">usb_umount</action>
+ </object>
+
+ <object type="action">
+ <action function="mount">usb</action>
+ <action function="set">tw_busy=1</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="usb_umount">
+ <object type="action">
+ <action function="unmount">usb</action>
+ </object>
+
+ <object type="action">
+ <action function="page">mount</action>
+ <action function="set">tw_busy=0</action>
+ </object>
+ </page>
+
+ <page name="system_readonly_check">
+ <object type="action">
+ <action function="checkpartitionlifetimewrites">/system</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_lifetime_writes" var2="1" />
+ <actions>
+ <action function="mountsystemtoggle">0</action>
+ <action function="page">mount</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_lifetime_writes" var2="0" />
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">system_readonly</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="reboot">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Reboot Menu</text>
+ </object>
+
+ <object type="button" style="rebootsystem">
+ <condition var1="tw_reboot_system" var2="1" />
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>System</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_poweroff" var2="1" />
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Power Off</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=poweroff</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to power off?</action>
+ <action function="set">tw_action_text1=Turning Off...</action>
+ <action function="set">tw_complete_text1=Turning Off...</action>
+ <action function="set">tw_slider_text=Swipe to Power Off</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_recovery" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Recovery</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=recovery</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_bootloader" var2="1" />
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Bootloader</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=bootloader</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_download_mode" var2="1" />
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Download</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=download</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="settings">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Settings</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row1_text_y%" />
+ <text>Zip file signature verification.</text>
+ <data variable="tw_signed_zip_verify" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>Use rm -rf instead of formatting.</text>
+ <data variable="tw_rm_rf" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Skip MD5 generation during backup.</text>
+ <data variable="tw_skip_md5_generate" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Enable MD5 verification of backup files.</text>
+ <data variable="tw_skip_md5_check" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>Use 24-hour clock.</text>
+ <data variable="tw_military_time" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row6_text_y%" />
+ <text>Simulate actions for theme testing.</text>
+ <data variable="tw_simulate_actions" />
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_simulate_actions" var2="1" />
+ <placement x="%col1_x%" y="%row7_text_y%" />
+ <text>Simulate failure for actions.</text>
+ <data variable="tw_simulate_fail" />
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Time Zone</text>
+ <action function="page">timezone</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>Screen</text>
+ <action function="page">screen</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Restore Defaults</text>
+ <action function="restoredefaultsettings"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Vibration Duration</text>
+ <action function="page">Vibrate</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="timezone">
+ <object type="template" name="header" />
+
+ <object type="listbox" style="scrolllist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%listbox_tz_height%" />
+ <text>Select Time Zone:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_time_zone_guisel" />
+ <listitem name="(UTC -11) Samoa, Midway Island">BST11;BDT</listitem>
+ <listitem name="(UTC -10) Hawaii">HST10;HDT</listitem>
+ <listitem name="(UTC -9) Alaska">AST9;ADT</listitem>
+ <listitem name="(UTC -8) Pacific Time">PST8;PDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -7) Mountain Time">MST7;MDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -6) Central Time">CST6;CDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -5) Eastern Time">EST5;EDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -4) Atlantic Time">AST4;ADT</listitem>
+ <listitem name="(UTC -3) Brazil, Buenos Aires">GRNLNDST3;GRNLNDDT</listitem>
+ <listitem name="(UTC -2) Mid-Atlantic">FALKST2;FALKDT</listitem>
+ <listitem name="(UTC -1) Azores, Cape Verde">AZOREST1;AZOREDT</listitem>
+ <listitem name="(UTC 0) London, Dublin, Lisbon">GMT0;BST,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +1) Berlin, Brussels, Paris">CET-1;CEST,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +2) Athens, Istanbul, South Africa">WET-2;WET,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +3) Moscow, Baghdad">SAUST-3;SAUDT</listitem>
+ <listitem name="(UTC +4) Abu Dhabi, Tbilisi, Muscat">WST-4;WDT</listitem>
+ <listitem name="(UTC +5) Yekaterinburg, Islamabad">PAKST-5;PAKDT</listitem>
+ <listitem name="(UTC +6) Almaty, Dhaka, Colombo">TASHST-6;TASHDT</listitem>
+ <listitem name="(UTC +7) Bangkok, Hanoi, Jakarta">THAIST-7;THAIDT</listitem>
+ <listitem name="(UTC +8) Beijing, Singapore, Hong Kong">TAIST-8;TAIDT</listitem>
+ <listitem name="(UTC +9) Tokyo, Seoul, Yakutsk">JST-9;JSTDT</listitem>
+ <listitem name="(UTC +10) Eastern Australia, Guam">EET-10;EETDT</listitem>
+ <listitem name="(UTC +11) Vladivostok, Solomon Islands">MET-11;METDT</listitem>
+ <listitem name="(UTC +12) Auckland, Wellington, Fiji">NZST-12;NZDT</listitem>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row_dst_text_y%" />
+ <text>Do you use daylight savings time (DST)?</text>
+ <data variable="tw_time_zone_guidst" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row_offset_text_y%" placement="5" />
+ <text>Offset (usually 0): %tw_time_zone_guioffset%</text>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col1_medium_x%" y="%row_offset_medium_y%" />
+ <text>None</text>
+ <action function="set">tw_time_zone_guioffset=0</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col2_medium_x%" y="%row_offset_medium_y%" />
+ <text>15</text>
+ <action function="set">tw_time_zone_guioffset=15</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col3_medium_x%" y="%row_offset_medium_y%" />
+ <text>30</text>
+ <action function="set">tw_time_zone_guioffset=30</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col4_medium_x%" y="%row_offset_medium_y%" />
+ <text>45</text>
+ <action function="set">tw_time_zone_guioffset=45</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%tz_set_y%" />
+ <text>Set Time Zone</text>
+ <action function="setguitimezone"></action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%tz_current_y%" placement="5" />
+ <text>Current Time Zone: %tw_time_zone%</text>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="screen">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Screen Settings</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_screen_timeout_secs" op="=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ <text>Enable screen timeout.</text>
+ <image resource="checkbox_false" />
+ <action function="set">tw_screen_timeout_secs=60</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ <text>Enable screen timeout.</text>
+ <image resource="checkbox_true" />
+ <action function="set">tw_screen_timeout_secs=0</action>
+ </object>
+
+ <object type="slidervalue">
+ <conditions>
+ <condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ </conditions>
+ <placement x="col1_x" y="%row4_text_y%" w="%slidervalue_w%" />
+ <text>Screen timeout in seconds:</text>
+ <data variable="tw_screen_timeout_secs" min="15" max="300" />
+ </object>
+
+ <object type="slidervalue">
+ <condition var1="tw_has_brightnesss_file" var2="1" />
+ <placement x="col1_x" y="%row12_text_y%" w="%slidervalue_w%" />
+ <text>Brightness: %tw_brightness_pct%%</text>
+ <data variable="tw_brightness_pct" min="10" max="100" />
+ <actions>
+ <action function="set">tw_brightness=%tw_brightness_max%</action>
+ <action function="compute">tw_brightness*%tw_brightness_pct%</action>
+ <action function="compute">tw_brightness/100</action>
+ <action function="setbrightness">%tw_brightness%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="Vibrate">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Vibration Settings :</text>
+ </object>
+
+ <object type="slidervalue">
+ <placement x="col1_x" y="%row4_text_y%" w="%slidervalue_w%" />
+ <text>Button Vibration:</text>
+ <data variable="tw_button_vibrate" min="0" max="300" />
+ </object>
+
+ <object type="slidervalue">
+ <placement x="col1_x" y="%row8_text_y%" w="%slidervalue_w%" />
+ <text>Keyboard Vibration:</text>
+ <data variable="tw_keyboard_vibrate" min="0" max="300" />
+ </object>
+
+ <object type="slidervalue">
+ <placement x="col1_x" y="%row12_text_y%" w="%slidervalue_w%" />
+ <text>Action Vibration:</text>
+ <data variable="tw_action_vibrate" min="0" max="500" />
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="advanced">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Advanced</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Copy Log to SD</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=copylog</action>
+ <action function="set">tw_text1=Copy Log to SD Card?</action>
+ <action function="set">tw_action_text1=Copying Log to SD Card...</action>
+ <action function="set">tw_complete_text1=Log Copy Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Fix Permissions</text>
+ <action function="page">fixperms</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_allow_partition_sdcard" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Partition SD Card</text>
+ <action function="page">partsdcard</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>File Manager</text>
+ <action function="page">filemanagerlist</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Terminal Command</text>
+ <action function="page">terminalfolder</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>Reload Theme</text>
+ <action function="reload"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>ADB Sideload</text>
+ <action function="page">sideload</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_show_dumlock" var2="1" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>HTC Dumlock</text>
+ <action function="page">htcdumlock</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_has_injecttwrp" var2="1" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Re-Inject TWRP</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=reinjecttwrp</action>
+ <action function="set">tw_text1=Re-Inject TWRP?</action>
+ <action function="set">tw_action_text1=Re-Injecting TWRP...</action>
+ <action function="set">tw_complete_text1=TWRP Injection Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="partsdcard">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Partition SD Card</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text></text>
+ <image resource="minus_button" />
+ <action function="addsubtract">tw_sdext_size-128</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sd_plus_x%" y="%row1_y%" />
+ <text></text>
+ <image resource="plus_button" />
+ <action function="addsubtract">tw_sdext_size+128</action>
+ </object>
+
+ <object type="text">
+ <placement x="%sdext_text_x%" y="%sdext_text_y%" />
+ <text>EXT Size: %tw_sdext_size%</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%sdswap_button_y%" />
+ <text></text>
+ <image resource="minus_button" />
+ <action function="addsubtract">tw_swap_size-32</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sd_plus_x%" y="%sdswap_button_y%" />
+ <text></text>
+ <image resource="plus_button" />
+ <action function="addsubtract">tw_swap_size+32</action>
+ </object>
+
+ <object type="text">
+ <placement x="%sdswap_text_x%" y="%sdswap_text_y%" />
+ <text>Swap Size: %tw_swap_size%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%sdfilesystem_text_y%" />
+ <text>File system: %tw_sdpart_file_system%</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%sdfilesystem_button_y%" />
+ <text>EXT3</text>
+ <action function="set">tw_sdpart_file_system=ext3</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_sdext_disable_ext4" var2="0" />
+ <placement x="%col2_x%" y="%sdfilesystem_button_y%" />
+ <text>EXT4</text>
+ <action function="set">tw_sdpart_file_system=ext4</action>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row12_text_y%" />
+ <text>You will lose all files on your SD card!</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row13_text_y%" />
+ <text>This action cannot be undone!</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Partition</text>
+ <action function="page">partsdcardaction</action>
+ <actions>
+ <action function="set">tw_back=partsdcard</action>
+ <action function="set">tw_action=partitionsd</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=set</action>
+ <action function="set">tw_action2_param=tw_zip_location=/sdcard</action>
+ <action function="set">tw_action_text1=Partitioning SD Card...</action>
+ <action function="set">tw_action_text2=This will take a few minutes.</action>
+ <action function="set">tw_complete_text1=Partitioning Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="htcdumlock">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>HTC Dumlock</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Restore Original Boot</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=htcdumlockrestoreboot</action>
+ <action function="set">tw_text1=Restore original boot image?</action>
+ <action function="set">tw_action_text1=Restoring Original Boot...</action>
+ <action function="set">tw_complete_text1=Restore Original Boot Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Reflash Recovery</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=htcdumlockreflashrecovery</action>
+ <action function="set">tw_text1=Reflash recovery to boot?</action>
+ <action function="set">tw_action_text1=Flashing recovery to boot...</action>
+ <action function="set">tw_complete_text1=Recovery Flash to Boot Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Install HTC Dumlock</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=installhtcdumlock</action>
+ <action function="set">tw_text1=Install HTC dumlock files to ROM?</action>
+ <action function="set">tw_action_text1=Installing HTC Dumlock...</action>
+ <action function="set">tw_complete_text1=HTC Dumlock Install Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="lock">
+ <background color="#000000A0" />
+
+ <object type="image">
+ <image resource="unlock-icon" />
+ <placement x="%center_x%" y="%lock_y%" placement="4" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Unlock</text>
+ <action function="overlay"></action>
+ </object>
+ </page>
+
+ <page name="filemanagerlist">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>File Manager: Select a File or Folder</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row1_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_file_location1%</text>
+ <filter folders="1" files="1" />
+ <path name="tw_file_location1" default="/" />
+ <data name="tw_filename1" />
+ <selection name="tw_selection1" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <actions>
+ <action function="set">tw_fm_type=File</action>
+ <action function="set">tw_fm_isfolder=0</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_filename1" op="modified" />
+ <actions>
+ <action function="page">filemanageroptions</action>
+ </actions>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select</text>
+ <actions>
+ <action function="set">tw_filename1=tw_file_location1</action>
+ <action function="set">tw_fm_isfolder=1</action>
+ <action function="set">tw_fm_type=Folder</action>
+ <action function="page">filemanageroptions</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanageroptions">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>%tw_fm_type% Selected:</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>%tw_filename1%</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="0" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Copy File</text>
+ <actions>
+ <action function="set">tw_filemanager_command=cp</action>
+ <action function="set">tw_fm_text1=Copying</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Copy Folder</text>
+ <actions>
+ <action function="set">tw_filemanager_command=cd &quot;%tw_file_location1%&quot; &amp;&amp; cd .. &amp;&amp; cp -R</action>
+ <action function="set">tw_fm_text1=Copying</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Move</text>
+ <actions>
+ <action function="set">tw_filemanager_command=mv</action>
+ <action function="set">tw_fm_text1=Moving</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>chmod 755</text>
+ <actions>
+ <action function="set">tw_filemanager_command=chmod 755</action>
+ <action function="set">tw_fm_text1=chmod 755</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>chmod</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=0000</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerchmod</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Delete</text>
+ <actions>
+ <action function="set">tw_filemanager_command=rm -rf</action>
+ <action function="set">tw_fm_text1=Deleting</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="0" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Rename File</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=tw_selection1</action>
+ <action function="set">tw_fm_text1=Renaming</action>
+ <action function="set">tw_filemanager_command=mv</action>
+ <action function="page">filemanagerrenamefile</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="1" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Rename Folder</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=tw_selection1</action>
+ <action function="set">tw_fm_text1=Renaming</action>
+ <action function="set">tw_filemanager_command=cd &quot;%tw_file_location1%&quot; &amp;&amp; cd .. &amp;&amp; mv</action>
+ <action function="page">filemanagerrenamefolder</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanagerlist</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="choosedestinationfolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>Browse to Destination Folder &amp; Press Select</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row1_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_file_location2%</text>
+ <filter folders="1" files="0" />
+ <path name="tw_file_location2" default="/" />
+ <data name="tw_filename2" />
+ <selection name="tw_selection2" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select</text>
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=%tw_file_location2%</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerrenamefile">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter a New %tw_fm_type% Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="1" maxlen="128" />
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=&quot;%tw_file_location1%/%tw_filemanager_rename%&quot;</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerrenamefolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter a New %tw_fm_type% Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="1" maxlen="128" />
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=%tw_filemanager_rename%</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerchmod">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter New Permissions</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="3" maxlen="4" allow="0123456789" />
+ <actions>
+ <action function="set">tw_filemanager_command=chmod %tw_filemanager_rename%</action>
+ <action function="set">tw_fm_text1=chmod %tw_filemanager_rename%</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerconfirm">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>%tw_fm_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>%tw_filename1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5"/>
+ <text>%tw_fm_text2%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5"/>
+ <text>%tw_fm_text3%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row10_text_y%" placement="5"/>
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="slider">
+ <action function="page">filemanageracction</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">%tw_back%</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanageracction">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_fm_text1%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_back=filemanagerlist</action>
+ <action function="set">tw_complete_text1=File Operation Complete</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_complete_text1=File Operation Complete</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_include_text3" var2="0" />
+ <actions>
+ <action function="cmd">%tw_filemanager_command% &quot;%tw_filename1%&quot;</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_include_text3" var2="1" />
+ <actions>
+ <action function="cmd">%tw_filemanager_command% &quot;%tw_filename1%&quot; &quot;%tw_fm_text3%&quot;</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="decrypt">
+ <object type="template" name="header" />
+
+ <object type="action">
+ <condition var1="tw_crypto_pwtype" var2="2" />
+ <action function="page">decrypt_pattern</action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter Your Password</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_crypto_display%</text>
+ <data name="tw_crypto_password" mask="*" maskvariable="tw_crypto_display" />
+ <restrict minlen="1" maxlen="254" />
+ <actions>
+ <action function="page">trydecrypt</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Password Failed, Please Try Again</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="decrypt_pattern">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter Your Pattern</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Pattern Failed, Please Try Again</text>
+ </object>
+
+ <object type="patternpassword">
+ <placement x="%pattern_x%" y="%pattern_y%" w="%pattern_width%" h="%pattern_width%" />
+ <dot color="%pattern_dot_color%" activecolor="%pattern_dot_color_active%" radius="%pattern_dot_radius%" />
+ <line color="%pattern_line_color%" width="%pattern_line_width%" />
+ <data name="tw_crypto_password"/>
+ <action function="page">trydecrypt</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row4_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="trydecrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Trying Decryption with Your Password</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="decrypt"></action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_password_fail=1</action>
+ <action function="page">decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="terminalfolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>Browse to Starting Folder</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row1_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_terminal_location%</text>
+ <filter folders="1" files="0" />
+ <path name="tw_terminal_location" default="/" />
+ <data name="tw_terminal" />
+ <selection name="tw_terminal_selection" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select</text>
+ <actions>
+ <action function="page">terminalcommand</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="terminalcommand">
+ <object type="template" name="header" />
+
+ <object type="console">
+ <placement x="%console_x%" y="0" w="%console_width%" h="%terminal_console_height%" />
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%terminal_text_y%" placement="0" />
+ <text>Starting Path: %tw_terminal_location%</text>
+ </object>
+
+ <object type="input">
+ <condition var1="tw_terminal_state" var2="0" />
+ <placement x="%col1_x%" y="%terminal_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_terminal_command%</text>
+ <font resource="fixed" color="%text_color%" />
+ <data name="tw_terminal_command" />
+ <restrict minlen="1" />
+ <action function="terminalcommand">%tw_terminal_command%</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <condition var1="tw_terminal_state" var2="1" />
+ <placement x="%filemanager_select_x%" y="%terminal_button_y%" />
+ <text>KILL</text>
+ <action function="killterminal"></action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">terminalfolder</action>
+ </object>
+ </page>
+
+ <page name="sideload">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>ADB Sideload</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>Wipe Dalvik Cache.</text>
+ <data variable="tw_wipe_dalvik" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Wipe Cache.</text>
+ <data variable="tw_wipe_cache" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Start Sideload</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=adbsideload</action>
+ <action function="set">tw_action_text1=ADB Sideload</action>
+ <action function="set">tw_action_text2=Usage: adb sideload filename.zip</action>
+ <action function="set">tw_complete_text1=ADB Sideload Complete</action>
+ <action function="set">tw_has_cancel=1</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="set">tw_cancel_action=adbsideloadcancel</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="fixperms">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>Fix Permissions</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>Note: Fixing permissions is rarely needed.</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Also fix SELinux contexts</text>
+ <data variable="tw_fixperms_restorecon" />
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Fixing SELinux contexts may cause</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>your device to not boot properly.</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Fix Permissions</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=fixpermissions</action>
+ <action function="set">tw_action_text1=Fixing Permissions...</action>
+ <action function="set">tw_complete_text1=Fix Permissions Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="installsu">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>Install SuperSU?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>Your device does not appear to be rooted.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5"/>
+ <text>Install SuperSU now?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5"/>
+ <text>This will root your device.</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row3_y%" />
+ <text>Do Not Install</text>
+ <action function="set">tw_page_done=1</action>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Install</text>
+ <actions>
+ <action function="set">tw_action=installsu</action>
+ <action function="set">tw_action_text1=Installing SuperSU</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="page">singleaction_page</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="system_readonly">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Keep System Read Only?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>TWRP can leave your system partition unmodified</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>to make it easier for you to take official updates.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>TWRP will be unable to prevent the stock ROM from</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>replacing TWRP and will not offer to root your device.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row6_text_y%" placement="5" />
+ <text>Installing zips or performing adb operations may still</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row7_text_y%" placement="5" />
+ <text>modify the system partition.</text>
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_is_encrypted" var2="0" />
+ <placement x="%col1_x%" y="%row8_text_y%" />
+ <text>Never show this screen during boot again</text>
+ <data variable="tw_never_show_system_ro_page" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row10_text_y%" />
+ <text>Keep Read Only</text>
+ <actions>
+ <action function="mountsystemtoggle">1</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Allow Modifications</text>
+ <actions>
+ <action function="mountsystemtoggle">0</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+ </pages>
+</recovery>
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-10.dat b/gui/devices/resources/fonts/Roboto-Condensed-10.dat
new file mode 100644
index 000000000..02e869b78
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-10.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-12.dat b/gui/devices/resources/fonts/Roboto-Condensed-12.dat
new file mode 100644
index 000000000..b48c4f213
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-12.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-14.dat b/gui/devices/resources/fonts/Roboto-Condensed-14.dat
new file mode 100644
index 000000000..f7b174cb1
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-14.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-16.dat b/gui/devices/resources/fonts/Roboto-Condensed-16.dat
new file mode 100644
index 000000000..19c11470d
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-16.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-20.dat b/gui/devices/resources/fonts/Roboto-Condensed-20.dat
new file mode 100644
index 000000000..531d5fdaf
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-20.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-25.dat b/gui/devices/resources/fonts/Roboto-Condensed-25.dat
new file mode 100644
index 000000000..7cee713e7
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-25.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-30.dat b/gui/devices/resources/fonts/Roboto-Condensed-30.dat
new file mode 100644
index 000000000..621b33214
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-30.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-40.dat b/gui/devices/resources/fonts/Roboto-Condensed-40.dat
new file mode 100644
index 000000000..ff23add82
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-40.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-50.dat b/gui/devices/resources/fonts/Roboto-Condensed-50.dat
new file mode 100644
index 000000000..ae9c0f64d
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-50.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Condensed-60.dat b/gui/devices/resources/fonts/Roboto-Condensed-60.dat
new file mode 100644
index 000000000..22f9accd1
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Condensed-60.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-10.dat b/gui/devices/resources/fonts/Roboto-Regular-10.dat
new file mode 100644
index 000000000..b1faa7d1c
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-10.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-12.dat b/gui/devices/resources/fonts/Roboto-Regular-12.dat
new file mode 100644
index 000000000..1c9f058c3
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-12.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-14.dat b/gui/devices/resources/fonts/Roboto-Regular-14.dat
new file mode 100644
index 000000000..5a6fff8b9
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-14.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-16.dat b/gui/devices/resources/fonts/Roboto-Regular-16.dat
new file mode 100644
index 000000000..9f6d90005
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-16.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-20.dat b/gui/devices/resources/fonts/Roboto-Regular-20.dat
new file mode 100644
index 000000000..6588b41e7
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-20.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-25.dat b/gui/devices/resources/fonts/Roboto-Regular-25.dat
new file mode 100644
index 000000000..392cce97d
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-25.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-30.dat b/gui/devices/resources/fonts/Roboto-Regular-30.dat
new file mode 100644
index 000000000..9f8082ccc
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-30.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-40.dat b/gui/devices/resources/fonts/Roboto-Regular-40.dat
new file mode 100644
index 000000000..637d9fe5b
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-40.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-50.dat b/gui/devices/resources/fonts/Roboto-Regular-50.dat
new file mode 100644
index 000000000..aecce38f0
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-50.dat
Binary files differ
diff --git a/gui/devices/resources/fonts/Roboto-Regular-60.dat b/gui/devices/resources/fonts/Roboto-Regular-60.dat
new file mode 100644
index 000000000..5840beda2
--- /dev/null
+++ b/gui/devices/resources/fonts/Roboto-Regular-60.dat
Binary files differ
diff --git a/gui/devices/watch/res/watch.xml b/gui/devices/watch/res/watch.xml
new file mode 100644
index 000000000..28198fb2d
--- /dev/null
+++ b/gui/devices/watch/res/watch.xml
@@ -0,0 +1,3727 @@
+<?xml version="1.0"?>
+
+<recovery>
+ <styles>
+ <style name="buttontext">
+ <highlight color="%highlight_color%" />
+ <font resource="font" color="%button_text_color%" />
+ </style>
+
+ <style name="button">
+ <style name="buttontext" />
+ <image resource="main_button" />
+ </style>
+
+ <style name="mediumbutton">
+ <style name="buttontext" />
+ <image resource="medium_button" />
+ </style>
+
+ <style name="fillbutton">
+ <style name="buttontext" />
+ <fill color="%button_fill_color%" />
+ </style>
+
+ <style name="rebootsystem">
+ <condition var1="tw_reboot_system" var2="1" />
+ <style name="button" />
+ <text>Reboot System</text>
+ <actions>
+ <action function="set">tw_back=main2</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=system</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_text3=</action>
+ <action function="set">tw_text4=</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </style>
+
+ <style name="scrolllist">
+ <highlight color="%fileselector_highlight_color%" />
+ <header background="%fileselector_header_background%" textcolor="%fileselector_header_textcolor%" separatorcolor="%fileselector_header_separatorcolor%" separatorheight="%fileselector_header_separatorheight%" />
+ <fastscroll linecolor="%fastscroll_linecolor%" rectcolor="%fastscroll_rectcolor%" w="%fastscroll_w%" linew="%fastscroll_linew%" rectw="%fastscroll_rectw%" recth="%fastscroll_recth%" />
+ <separator color="%fileselector_separatorcolor%" height="%fileselector_separatorheight%" />
+ <background color="%fileselector_background%" />
+ <font resource="filelist" spacing="%fileselector_spacing%" color="%text_color%" highlightcolor="%fileselector_highlight_font_color%" />
+ </style>
+
+ <style name="fileselector">
+ <style name="scrolllist" />
+ <icon folder="folder_icon" file="file_icon" />
+ <sort name="tw_gui_sort_order" />
+ </style>
+
+ <style name="partitionlist">
+ <style name="scrolllist" />
+ <icon selected="checkbox_true" unselected="checkbox_false" />
+ </style>
+
+ <style name="text">
+ <font resource="font" color="%text_color%" />
+ </style>
+
+ <style name="checkbox">
+ <font resource="font" color="%text_color%" />
+ <image checked="checkbox_true" unchecked="checkbox_false" />
+ </style>
+
+ <style name="slider">
+ <text>Swipe to Confirm</text>
+ <font resource="font" color="%text_color%" />
+ <placement x="%center_x%" y="%slider_y%" placement="5" />
+ <resource base="slider" used="slider-used" touch="slider-touch" />
+ </style>
+
+ <style name="console">
+ <color foreground="%console_foreground%" background="%console_background%" scroll="%console_scroll%" />
+ <font resource="fixed" />
+ <fastscroll linecolor="%fastscroll_linecolor%" rectcolor="%fastscroll_rectcolor%" w="%fastscroll_w%" linew="%fastscroll_linew%" rectw="%fastscroll_rectw%" recth="%fastscroll_recth%" />
+ </style>
+
+ <style name="input">
+ <background color="%input_background_color%" />
+ <cursor color="%input_cursor_color%" hasfocus="1" width="%input_cursor_width%" />
+ <font resource="font" color="%text_color%" />
+ </style>
+
+ <style name="slidervalue">
+ <font resource="font" color="%text_color%" />
+ <colors line="%slidervalue_line_clr%" slider="%slidervalue_slider_clr%" />
+ <dimensions lineh="%slidervalue_lineh%" linepadding="%slidervalue_padding%" sliderw="%slidervalue_sliderw%" sliderh="%slidervalue_sliderh%" />
+ </style>
+ </styles>
+
+ <pages>
+ <page name="main">
+ <object type="action">
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="main2">
+ <object type="template" name="twrpheader" />
+
+ <object type="template" name="header" />
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_home_y%" />
+ <text>Install</text>
+ <action function="page">install_select</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_home_y%" />
+ <text>Wipe</text>
+ <action function="page">wipe</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_home_y%" />
+ <text>Backup</text>
+ <action function="page">backup</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_home_y%" />
+ <text>Restore</text>
+ <action function="page">restore</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_home_y%" />
+ <text>Mount</text>
+ <action function="page">mount</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row3_home_y%" />
+ <text>Settings</text>
+ <action function="page">settings</action>
+ </object>
+
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_home_y%" />
+ <text>Advanced</text>
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row4_home_y%" />
+ <text>Reboot</text>
+ <action function="page">reboot</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="install_select">
+ <object type="template" name="twrpheader" />
+
+ <object type="template" name="header" />
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_home_y%" />
+ <text>Install Zips</text>
+ <actions>
+ <action function="queueclear"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_home_y%" />
+ <text>Install Images</text>
+ <action function="page">install_image</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="install">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Select Zip to Install</text>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%row1_text_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=install</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%fileselector_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_zip_location%</text>
+ <filter extn=".zip" folders="1" files="1" />
+ <path name="tw_zip_location" default="/sdcard" />
+ <data name="tw_filename" />
+ <selection name="tw_file" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <condition var1="tw_filename" op="modified" />
+ <actions>
+ <action function="queuezip"></action>
+ <action function="page">flash_confirm</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">install_select</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="flash_confirm">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>This operation may install incompatible</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>software and render your device unusable.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Folder and File:</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%" />
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_zip_location%</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%" />
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>%tw_file%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>Press back to cancel adding this zip.</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row6_text_y%" />
+ <text>Zip file signature verification.</text>
+ <data variable="tw_signed_zip_verify" />
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_has_injecttwrp" var2="1" />
+ <placement x="%col1_x%" y="%row7_text_y%" />
+ <text>Inject TWRP after install.</text>
+ <data variable="tw_inject_after_zip" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row11_text_y%" placement="5" />
+ <text>File %tw_zip_queue_count% of max of 10</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Confirm Flash</text>
+ <action function="flash">flash_zip</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_zip_queue_count" op="!=" var2="10"></condition>
+ <placement x="%col1_x%" y="%row_queue_y%" />
+ <text>Add More Zips</text>
+ <action function="page">install</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row_queue_y%" />
+ <text>Clear Zip Queue</text>
+ <actions>
+ <action function="queueclear"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="cancelzip"></action>
+ <action function="page">install</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+ </page>
+
+ <page name="flash_zip">
+ <object type="template" name="header" />
+
+ <object type="console">
+ <placement x="%console_x%" y="%row1_y%" w="%console_width%" h="%console_install_height%" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row10_text_y%" placement="5" />
+ <text>Flashing file %tw_zip_index% of %tw_zip_queue_count%</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%"/>
+ <placement x="%center_x%" y="%row11_text_y%" placement="5" />
+ <text>%tw_filename%</text>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <action function="page">flash_done</action>
+ </object>
+ </page>
+
+ <page name="flash_done">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Zip Install Complete</text>
+ </object>
+
+ <object type="console">
+ <placement x="%console_x%" y="%row1_y%" w="%console_width%" h="%console_installdone_height%" />
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Wipe cache/dalvik</text>
+ <actions>
+ <action function="set">tw_back=flash_done</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=/cache</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=wipe</action>
+ <action function="set">tw_action2_param=dalvik</action>
+ <action function="set">tw_text1=Wipe Cache &amp; Dalvik?</action>
+ <action function="set">tw_action_text1=Wiping Cache &amp; Dalvik...</action>
+ <action function="set">tw_complete_text1=Cache &amp; Dalvik Wipe Complete</action>
+ <action function="set">tw_slider_text=Swipe to Wipe</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button" style="rebootsystem">
+ <placement x="%col2_x%" y="%row4_y%" />
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%zip_status_y%" placement="5" />
+ <text>Failed</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" var2="0" />
+ <font resource="font" color="%text_success_color%" />
+ <placement x="%center_x%" y="%zip_status_y%" placement="5" />
+ <text>Successful</text>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=install</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="install_image">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Select Image to Install</text>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%row1_text_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=install_image</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row3_text_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_zip_location%</text>
+ <filter extn=".img" folders="1" files="1" />
+ <path name="tw_zip_location" default="/sdcard" />
+ <data name="tw_filename" />
+ <selection name="tw_file" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <condition var1="tw_filename" op="modified" />
+ <action function="page">flashimage_confirm</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">install_select</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="flashimage_confirm">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%flash_list_height%" />
+ <text>Select Partition to Flash Image:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_flash_partition" />
+ <listtype name="flashimg" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row8_text_y%" placement="5" />
+ <text>Folder:</text>
+ </object>
+
+ <object type="text">
+ <font resource="mediumfont" color="%text_color%" />
+ <placement x="%center_x%" y="%row9_text_y%" placement="5" />
+ <text>%tw_zip_location%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row10_text_y%" placement="5" />
+ <text>File to flash:</text>
+ </object>
+
+ <object type="text" >
+ <font resource="mediumfont" color="%text_color%" />
+ <placement x="%center_x%" y="%row11_text_y%" placement="5" />
+ <text>%tw_file%</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Confirm Flash</text>
+ <actions>
+ <action function="set">tw_back=flashimage_confirm</action>
+ <action function="set">tw_action=flashimage</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_action_text1=Flashing Image...</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_complete_text1=Image Flashed</action>
+ <action function="page">action_page</action>
+ </actions>
+ <action function="flashimage"></action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=install_image</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="clear_vars">
+ <object type="action">
+ <action function="set">tw_operation_state=0</action>
+ <action function="set">tw_text1=</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_text3=</action>
+ <action function="set">tw_text4=</action>
+ <action function="set">tw_action_text1=</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="set">tw_action_param=</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_action2=</action>
+ <action function="set">tw_action2_param=</action>
+ <action function="set">tw_has_cancel=0</action>
+ <action function="set">tw_cancel_action=</action>
+ <action function="set">tw_cancel_param=</action>
+ <action function="set">tw_show_exclamation=0</action>
+ <action function="set">tw_show_reboot=0</action>
+ <action function="page">%tw_clear_destination%</action>
+ </object>
+ </page>
+
+ <page name="confirm_action">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_text2%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_text3%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>%tw_text4%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row15_text_y%" placement="5" />
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="slider">
+ <text>%tw_slider_text%</text>
+ <action function="page">action_page</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+ </page>
+
+ <page name="action_page">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_action_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_action_text2%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="button" style="mediumbutton">
+ <condition var1="tw_has_cancel" var2="1" />
+ <placement x="%col_center_medium_x%" y="%row4_y%" />
+ <text>Cancel</text>
+ <action function="%tw_cancel_action%">%tw_cancel_param%</action>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="0" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="1" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ <action function="%tw_action2%">%tw_action2_param%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="singleaction_page">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_action_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_action_text2%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="0" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_has_action2" var2="1" />
+ <actions>
+ <action function="%tw_action%">%tw_action_param%</action>
+ <action function="%tw_action2%">%tw_action2_param%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="action_complete">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_complete_text1%</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Failed</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_operation_status" var2="0" />
+ <font resource="font" color="%text_success_color%" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Successful</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_clear_destination=main2</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="filecheck">
+ <object type="action">
+ <action function="fileexists">%tw_filecheck%</action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_fileexists=1</action>
+ <action function="page">%tw_existpage%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="1" />
+ </conditions>
+ <actions>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">%tw_notexistpage%</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="rebootcheck">
+ <object type="action">
+ <condition var1="tw_backup_system_size" op="&gt;=" var2="%tw_min_system%" />
+ <action function="reboot">%tw_action_param%</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_backup_system_size" op="&lt;" var2="%tw_min_system%" />
+ <action function="page">confirm_action</action>
+ </object>
+ </page>
+
+ <page name="wipe">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Factory Reset</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Wipes Data, Cache, and Dalvik</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_has_data_media" var2="1" />
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>(not including internal storage)</text>
+ </object>
+
+ <object type="text">
+ <conditions>
+ <condition var1="tw_has_android_secure" var2="1" />
+ <condition var1="fileexists" var2="/and-sec" />
+ </conditions>
+ <placement x="%col2_x%" y="%row4_text_y%" placement="1" />
+ <text>Android Secure </text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_has_sdext_partition" var2="1" />
+ <placement x="%col2_x%" y="%row4_text_y%" />
+ <text> SD-EXT</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>Most of the time this is</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row6_text_y%" placement="5" />
+ <text>the only wipe that you need.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row16_text_y%" placement="5" />
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%wipe_button_y%" />
+ <text>Advanced Wipe</text>
+ <actions>
+ <action function="set">partitionlisterror=0</action>
+ <action function="page">advancedwipe</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_has_data_media" var2="1" />
+ <placement x="%col2_x%" y="%wipe_button_y%" />
+ <text>Format Data</text>
+ <actions>
+ <action function="page">formatdata</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_is_encrypted" var2="1" />
+ <condition var1="tw_has_data_media" var2="0" />
+ </conditions>
+ <placement x="%col2_x%" y="%wipe_button_y%" />
+ <text>Wipe Encryption</text>
+ <actions>
+ <action function="set">tw_back=wipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=DATAMEDIA</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Wipe Encryption from Data?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting Data...</action>
+ <action function="set">tw_complete_text1=Data Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Format Data</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Factory Reset</text>
+ <actions>
+ <action function="set">tw_back=wipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=data</action>
+ <action function="set">tw_action_text1=Factory Reset...</action>
+ <action function="set">tw_complete_text1=Factory Reset Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+ </page>
+
+ <page name="advancedwipe">
+ <object type="template" name="header" />
+
+ <object type="action">
+ <action function="set">tw_wipe_list=</action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Wipe Menu</text>
+ </object>
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%wipe_list_height%" />
+ <text>Select Partitions to Wipe:</text>
+ <data name="tw_wipe_list" />
+ <listtype name="wipe" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Wipe</text>
+ <actions>
+ <action function="set">tw_back=advancedwipe</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=LIST</action>
+ <action function="set">tw_text1=Wipe Selected Partition(s)?</action>
+ <action function="set">tw_action_text1=Wiping Partition(s)...</action>
+ <action function="set">tw_complete_text1=Wipe Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%wipe_button_row1%" w="%button_fill_full_width%" h="%button_fill_half_height%" />
+ <text>Repair or Change File System</text>
+ <actions>
+ <action function="checkpartitionlist"></action>
+ <action function="page">checkpartitionlist</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="partitionlisterror" var2="1" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%invalid_partition_y%" placement="5" />
+ <text>Invalid partition selection</text>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">wipe</action>
+ </object>
+ </page>
+
+ <page name="formatdata">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Format Data will wipe all of your apps,</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>backups, pictures, videos, media, and</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>removes encryption on internal storage.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>This cannot be undone. Press back to cancel.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>Type yes to continue.</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row6_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_confirm_formatdata%</text>
+ <data name="tw_confirm_formatdata" />
+ <restrict minlen="3" maxlen="3" allow="yes" />
+ <action function="page">formatdata_confirm</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">wipe</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="formatdata_confirm">
+ <object type="action">
+ <condition var1="tw_confirm_formatdata" op="=" var2="yes" />
+ <actions>
+ <action function="set">tw_back=formatdata</action>
+ <action function="set">tw_action=wipe</action>
+ <action function="set">tw_action_param=DATAMEDIA</action>
+ <action function="set">tw_action_text1=Formatting Data...</action>
+ <action function="set">tw_complete_text1=Data Format Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_confirm_formatdata" op="!=" var2="yes" />
+ <action function="page">formatdata</action>
+ </object>
+ </page>
+
+ <page name="checkpartitionlist">
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=0</action>
+ <action function="getpartitiondetails"></action>
+ <action function="page">partitionoptions</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="!=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=1</action>
+ <action function="set">tw_wipe_list=</action>
+ <action function="page">advancedwipe</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="partitionoptions">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Partition Options for: %tw_partition_name%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Mount Point: %tw_partition_mount_point%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Current file system: %tw_partition_file_system%</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_is_present" op="!=" var2="0" />
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Present: Yes</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_is_present" op="=" var2="0" />
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Present: No</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_removable" op="!=" var2="0" />
+ <placement x="%col2_x%" y="%row3_text_y%" />
+ <text>Removable: Yes</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_partition_removable" op="=" var2="0" />
+ <placement x="%col2_x%" y="%row3_text_y%" />
+ <text>Removable: No</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Size: %tw_partition_size%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col2_x%" y="%row4_text_y%" />
+ <text>Used: %tw_partition_used%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>Free: %tw_partition_free%MB</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col2_x%" y="%row5_text_y%" />
+ <text>Backup Size: %tw_partition_backup_size%MB</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_can_resize" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Resize</text>
+ <actions>
+ <action function="set">tw_back=partitionoptions</action>
+ <action function="set">tw_action=resize</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=getpartitiondetails</action>
+ <action function="set">tw_text1=Resize %tw_partition_name%?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Resizing...</action>
+ <action function="set">tw_complete_text1=Resize Complete</action>
+ <action function="set">tw_slider_text=Swipe to Resize</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_can_repair" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Repair</text>
+ <actions>
+ <action function="set">tw_back=partitionoptions</action>
+ <action function="set">tw_action=repair</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Repair %tw_partition_name%?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Repairing...</action>
+ <action function="set">tw_complete_text1=Repair Complete</action>
+ <action function="set">tw_slider_text=Swipe to Repair</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Change File Sys</text>
+ <action function="page">selectfilesystem</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advancedwipe</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="refreshfilesystem">
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=0</action>
+ <action function="getpartitiondetails"></action>
+ <action function="page">selectfilesystem</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_check_partition_list" op="!=" var2="1" />
+ <actions>
+ <action function="set">partitionlisterror=1</action>
+ <action function="set">tw_wipe_list=</action>
+ <action function="page">advancedwipe</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="selectfilesystem">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Change file system for: %tw_partition_name%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Mount Point: %tw_partition_mount_point%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Current file system: %tw_partition_file_system%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>Proceed with caution!</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>EXT2</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext2</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT2?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>EXT3</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext3</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT3?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_ext" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>EXT4</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=ext4</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to EXT4?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_f2fs" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>F2FS</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=f2fs</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to F2FS?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_vfat" op="=" var2="1" />
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>FAT</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=vfat</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to FAT?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_partition_exfat" op="=" var2="1" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>exFAT</text>
+ <actions>
+ <action function="set">tw_back=refreshfilesystem</action>
+ <action function="set">tw_action=changefilesystem</action>
+ <action function="set">tw_action_param=%tw_partition_mount_point%</action>
+ <action function="set">tw_action_new_file_system=exfat</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=Change %tw_partition_name% to exFAT?</action>
+ <action function="set">tw_text2=</action>
+ <action function="set">tw_action_text1=Formatting...</action>
+ <action function="set">tw_complete_text1=Format Complete</action>
+ <action function="set">tw_slider_text=Swipe to Change</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">partitionoptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backup">
+ <object type="template" name="header" />
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%row1_header_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Backup Name: %tw_backup_name%</text>
+ <actions>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">backupname1</action>
+ </actions>
+ </object>
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%backup_list_y%" w="%listbox_width%" h="%backup_list_height%" />
+ <text>Select Partitions to Back Up:</text>
+ <data name="tw_backup_list" />
+ <listtype name="backup" />
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col2_x%" y="%backup_button_row1%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>More...</text>
+ <action function="page">backupoptions</action>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%backup_button_row2%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%backup_button_row1%" />
+ <text>Compression</text>
+ <data variable="tw_use_compression" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Back Up</text>
+ <action function="page">backup_run</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+ </page>
+
+ <page name="backupoptions">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>More Backup Options</text>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <conditions>
+ <condition var1="tw_include_encrypted_backup" var2="1" />
+ <condition var1="tw_encrypt_backup" var2="0" />
+ </conditions>
+ <placement x="%col1_x%" y="%row6_text_y%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>No Encryption</text>
+ <actions>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <conditions>
+ <condition var1="tw_include_encrypted_backup" var2="1" />
+ <condition var1="tw_encrypt_backup" var2="1" />
+ </conditions>
+ <placement x="%col1_x%" y="%row6_text_y%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>Using Encryption</text>
+ <actions>
+ <action function="set">tw_password_not_match=0</action>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col2_x%" y="%row6_text_y%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>Refresh Sizes</text>
+ <actions>
+ <action function="refreshsizes"></action>
+ <action function="page">backupoptions</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%backup_button_row2%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=backupotions</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>Enable compression.</text>
+ <data variable="tw_use_compression" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Skip MD5 generation during backup.</text>
+ <data variable="tw_skip_md5_generate" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <text>Disable Free Space Check.</text>
+ <data variable="tw_disable_free_space" />
+ <image checked="checkbox_true" unchecked="checkbox_false" />
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">backup</action>
+ </object>
+ </page>
+
+ <page name="backupname1">
+ <object type="action">
+ <condition var1="tw_backup_name" op="=" var2="(Auto Generate)" />
+ <action function="generatebackupname"></action>
+ </object>
+
+ <object type="action">
+ <action function="page">backupname2</action>
+ </object>
+ </page>
+
+ <page name="backupname2">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter a Backup Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_name%</text>
+ <data name="tw_backup_name" />
+ <restrict minlen="1" maxlen="64" allow=" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_.{}[]" />
+ <actions>
+ <action function="set">tw_filecheck=%tw_backups_folder%/%tw_backup_name%</action>
+ <action function="set">tw_existpage=backupname2</action>
+ <action function="set">tw_notexistpage=backup</action>
+ <action function="page">filecheck</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_fileexists" var2="1" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <font resource="font" color="%text_fail_color%" />
+ <text>A backup with that name already exists!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Append Date</text>
+ <action function="appenddatetobackupname"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="set">tw_backup_name=(Auto Generate)</action>
+ <action function="page">backup</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backupencryption">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Encrypt your backup?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter A Password:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_encrypt_display%</text>
+ <data name="tw_backup_password" mask="*" maskvariable="tw_backup_encrypt_display" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <action function="page">backupencryption2</action>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_not_match" var2="1" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Passwords Do Not Match</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backupoptions</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">backupoptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="backupencryption2">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Encrypt your backup?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter Password Again:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_encrypt_display2%</text>
+ <data name="tw_backup_password2" mask="*" maskvariable="tw_backup_encrypt_display2" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <actions>
+ <action function="page">checkbackuppassword</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backupoptions</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">backupoptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="checkbackuppassword">
+ <object type="action">
+ <condition var1="tw_backup_password2" var2="tw_backup_password" />
+ <actions>
+ <action function="set">tw_encrypt_backup=1</action>
+ <action function="page">backupoptions</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_backup_password2" op="!=" var2="tw_backup_password" />
+ <actions>
+ <action function="set">tw_encrypt_backup=0</action>
+ <action function="set">tw_password_not_match=1</action>
+ <action function="set">tw_backup_password=</action>
+ <action function="set">tw_backup_password2=</action>
+ <action function="set">tw_backup_encrypt_display=</action>
+ <action function="set">tw_backup_encrypt_display2=</action>
+ <action function="page">backupencryption</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="backup_run">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_operation% %tw_partition%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_file_progress%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>%tw_size_progress%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+
+
+ <object type="template" name="progress_bar" />
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col_center_medium_x%" y="%row4_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="cancelbackup"></action>
+ </actions>
+ </object>
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="nandroid">backup</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_cancel_backup" var2="0" />
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="set">tw_complete_text1=Backup Complete</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_cancel_backup" var2="1" />
+ <actions>
+ <action function="set">tw_back=backup</action>
+ <action function="set">tw_complete_text1=Backup Cancelled</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="restore">
+ <object type="template" name="header" />
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%row1_header_y%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row2_text_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>Select Package to Restore:</text>
+ <filter folders="1" files="0" nav="0" />
+ <path name="tw_backups_folder" />
+ <data name="tw_restore" default="" />
+ <selection name="tw_restore_name" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <condition var1="tw_restore" op="modified" />
+ <actions>
+ <action function="readBackup"></action>
+ <action function="page">restore_read</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="restore_read">
+ <object type="action">
+ <condition var1="tw_restore_encrypted" var2="1" />
+ <actions>
+ <action function="set">tw_password_fail=0</action>
+ <action function="page">restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_restore_encrypted" var2="0" />
+ <actions>
+ <action function="page">restore_select</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="restore_decrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Backup Encrypted</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Please Enter Your Password:</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_restore_display%</text>
+ <data name="tw_restore_password" mask="*" maskvariable="tw_restore_display" />
+ <restrict minlen="1" maxlen="32" allow="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890_" />
+ <actions>
+ <action function="page">try_restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Password Failed, Please Try Again</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">restore</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Delete</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; rm -rf &quot;%tw_restore_name%&quot;</action>
+ <action function="set">tw_text1=Delete Backup? %tw_restore_name%</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Deleting Backup...</action>
+ <action function="set">tw_complete_text1=Backup Delete Complete</action>
+ <action function="set">tw_slider_text=Swipe to Delete</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="try_restore_decrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Trying Decryption with Your Password</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="decrypt_backup"></action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_password_fail=1</action>
+ <action function="page">restore_decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">restore_select</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="restore_select">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%restore_list_height%" />
+ <text>Restoring: %tw_restore_name%</text>
+ <data name="tw_restore_list" selectedlist="tw_restore_selected" />
+ <listtype name="restore" />
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%backup_button_row2%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>Rename Backup</text>
+ <actions>
+ <action function="set">tw_backup_rename=</action>
+ <action function="set">tw_fileexists=0</action>
+ <action function="page">renamebackup</action>
+ </actions>
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col2_x%" y="%backup_button_row2%" w="%button_fill_main_width%" h="%button_fill_quarter_height%" />
+ <text>Delete Backup</text>
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; rm -rf &quot;%tw_restore_name%&quot;</action>
+ <action function="set">tw_text1=Delete Backup? %tw_restore_name%</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Deleting Backup...</action>
+ <action function="set">tw_complete_text1=Backup Delete Complete</action>
+ <action function="set">tw_slider_text=Swipe to Delete</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%backup_button_row1%" />
+ <text>Enable MD5 verification of backup.</text>
+ <data variable="tw_skip_md5_check" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Restore</text>
+ <action function="page">restore_run</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore</action>
+ </object>
+ </page>
+
+ <page name="renamebackup">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter a New Backup Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_backup_rename%</text>
+ <data name="tw_backup_rename" />
+ <restrict minlen="1" maxlen="64" allow=" abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890-_.{}[]" />
+ <actions>
+ <action function="set">tw_back=restore</action>
+ <action function="set">tw_action=cmd</action>
+ <action function="set">tw_action_param=cd %tw_backups_folder% &amp;&amp; mv &quot;%tw_restore_name%&quot; &quot;%tw_backup_rename%&quot;</action>
+ <action function="set">tw_text1=Rename Backup?</action>
+ <action function="set">tw_text2=This cannot be undone!</action>
+ <action function="set">tw_action_text1=Renaming Backup...</action>
+ <action function="set">tw_complete_text1=Backup Rename Complete</action>
+ <action function="set">tw_slider_text=Swipe to Rename</action>
+ <action function="set">tw_filecheck=%tw_backups_folder%/%tw_backup_rename%</action>
+ <action function="set">tw_existpage=renamebackup</action>
+ <action function="set">tw_notexistpage=confirm_action</action>
+ <action function="page">filecheck</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_fileexists" var2="1" />
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <font resource="font" color="%text_fail_color%" />
+ <text>A backup with that name already exists!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <action function="page">restore_select</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">restore_select</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="restore_run">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_operation% %tw_partition%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>%tw_size_progress%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <condition var1="tw_operation_state" var2="1" />
+ <actions>
+ <action function="set">tw_back=restore_select</action>
+ <action function="set">tw_complete_text1=Restore Complete</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <action function="nandroid">restore</action>
+ </object>
+ </page>
+
+ <page name="selectstorage">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%storage_list_height%" />
+ <text>Select Storage:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_storage_path" />
+ <listtype name="storage" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row4_y%" />
+ <text>OK</text>
+ <actions>
+ <action function="set">tw_clear_destination=%tw_back%</action>
+ <action function="page">clear_vars</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <actions>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="mount">
+ <object type="template" name="header" />
+
+ <object type="partitionlist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%mount_list_height%" />
+ <text>Select Partitions to Mount:</text>
+ <listtype name="mount" />
+ </object>
+
+ <object type="button" style="fillbutton">
+ <placement x="%col1_x%" y="%mount_storage_row%" w="%button_fill_full_width%" h="%button_fill_quarter_height%" />
+ <text>Storage: %tw_storage_display_name% (%tw_storage_free_size% MB)</text>
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">selectstorage</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_has_usb_storage" var2="1" />
+ <placement x="%col1_x%" y="row4_y" />
+ <text>USB Storage</text>
+ <action function="page">usb_mount</action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_has_mtp" var2="1" />
+ <condition var1="tw_mtp_enabled" var2="0" />
+ </conditions>
+ <placement x="%col2_x%" y="row4_y" />
+ <text>Enable MTP</text>
+ <action function="startmtp"></action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_has_mtp" var2="1" />
+ <condition var1="tw_mtp_enabled" var2="1" />
+ </conditions>
+ <placement x="%col2_x%" y="row4_y" />
+ <text>Disable MTP</text>
+ <action function="stopmtp"></action>
+ </object>
+
+ <object type="button">
+ <conditions>
+ <condition var1="tw_is_encrypted" var2="1" />
+ <condition var1="tw_is_decrypted" var2="0" />
+ </conditions>
+ <placement x="%col2_x%" y="row4_y" />
+ <text>Decrypt Data</text>
+ <action function="page">decrypt</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%system_ro_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_false" />
+ <action function="mountsystemtoggle">1</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%system_ro_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_mount_system_ro" op="!=" var2="0" />
+ <text>Only mount system read-only</text>
+ <image resource="checkbox_true" />
+ <actions>
+ <action function="set">tw_lifetime_writes=2</action>
+ <action function="page">system_readonly_check</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="usb_mount">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>USB Storage Mounted</text>
+ </object>
+
+ <object type="text" color="%text_color%">
+ <placement x="%col1_x%" y="%row1_text_y%" />
+ <font resource="font" />
+ <text>Be sure to safely remove your device</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>from your computer before unmounting!</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Unmount</text>
+ <action function="page">usb_umount</action>
+ </object>
+
+ <object type="action">
+ <action function="mount">usb</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="usb_umount">
+ <object type="action">
+ <action function="unmount">usb</action>
+ </object>
+
+ <object type="action">
+ <action function="page">mount</action>
+ </object>
+ </page>
+
+ <page name="system_readonly_check">
+ <object type="action">
+ <action function="checkpartitionlifetimewrites">/system</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_lifetime_writes" var2="1" />
+ <actions>
+ <action function="mountsystemtoggle">0</action>
+ <action function="page">mount</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_lifetime_writes" var2="0" />
+ <actions>
+ <action function="set">tw_back=mount</action>
+ <action function="page">system_readonly</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="reboot">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Reboot Menu</text>
+ </object>
+
+ <object type="button" style="rebootsystem">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>System</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_poweroff" var2="1" />
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Power Off</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=poweroff</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to power off?</action>
+ <action function="set">tw_action_text1=Turning Off...</action>
+ <action function="set">tw_complete_text1=Turning Off...</action>
+ <action function="set">tw_slider_text=Swipe to Power Off</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_recovery" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Recovery</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=recovery</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_reboot_bootloader" var2="1" />
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Bootloader</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=bootloader</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_download_mode" var2="1" />
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Download</text>
+ <actions>
+ <action function="set">tw_back=reboot</action>
+ <action function="set">tw_action=reboot</action>
+ <action function="set">tw_action_param=download</action>
+ <action function="set">tw_has_action2=0</action>
+ <action function="set">tw_text1=No OS Installed! Are you</action>
+ <action function="set">tw_text2=sure you wish to reboot?</action>
+ <action function="set">tw_action_text1=Rebooting...</action>
+ <action function="set">tw_complete_text1=Rebooting...</action>
+ <action function="set">tw_slider_text=Swipe to Reboot</action>
+ <action function="page">rebootcheck</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="settings">
+ <object type="template" name="header" />
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row1_header_y%" />
+ <text>Zip file signature verification.</text>
+ <data variable="tw_signed_zip_verify" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row1_text_y%" />
+ <text>Use rm -rf instead of formatting.</text>
+ <data variable="tw_rm_rf" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>Skip MD5 generation during backup.</text>
+ <data variable="tw_skip_md5_generate" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Enable MD5 verification of backup files.</text>
+ <data variable="tw_skip_md5_check" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Use 24-hour clock.</text>
+ <data variable="tw_military_time" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>Simulate actions for theme testing.</text>
+ <data variable="tw_simulate_actions" />
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_simulate_actions" var2="1" />
+ <placement x="%col1_x%" y="%row6_text_y%" />
+ <text>Simulate failure for actions.</text>
+ <data variable="tw_simulate_fail" />
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Time Zone</text>
+ <action function="page">timezone</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>Screen</text>
+ <action function="page">screen</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Restore Defaults</text>
+ <action function="restoredefaultsettings"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Vibration</text>
+ <action function="page">vibrate</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="timezone">
+ <object type="template" name="header" />
+
+ <object type="listbox" style="scrolllist">
+ <placement x="%listbox_x%" y="%row1_header_y%" w="%listbox_width%" h="%listbox_tz_height%" />
+ <text>Select Time Zone:</text>
+ <icon selected="radio_true" unselected="radio_false" />
+ <data name="tw_time_zone_guisel" />
+ <listitem name="(UTC -11) Samoa, Midway Island">BST11;BDT</listitem>
+ <listitem name="(UTC -10) Hawaii">HST10;HDT</listitem>
+ <listitem name="(UTC -9) Alaska">AST9;ADT</listitem>
+ <listitem name="(UTC -8) Pacific Time">PST8;PDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -7) Mountain Time">MST7;MDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -6) Central Time">CST6;CDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -5) Eastern Time">EST5;EDT,M3.2.0,M11.1.0</listitem>
+ <listitem name="(UTC -4) Atlantic Time">AST4;ADT</listitem>
+ <listitem name="(UTC -3) Brazil, Buenos Aires">GRNLNDST3;GRNLNDDT</listitem>
+ <listitem name="(UTC -2) Mid-Atlantic">FALKST2;FALKDT</listitem>
+ <listitem name="(UTC -1) Azores, Cape Verde">AZOREST1;AZOREDT</listitem>
+ <listitem name="(UTC 0) London, Dublin, Lisbon">GMT0;BST,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +1) Berlin, Brussels, Paris">CET-1;CEST,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +2) Athens, Istanbul, South Africa">WET-2;WET,M3.5.0,M10.5.0</listitem>
+ <listitem name="(UTC +3) Moscow, Baghdad">SAUST-3;SAUDT</listitem>
+ <listitem name="(UTC +4) Abu Dhabi, Tbilisi, Muscat">WST-4;WDT</listitem>
+ <listitem name="(UTC +5) Yekaterinburg, Islamabad">PAKST-5;PAKDT</listitem>
+ <listitem name="(UTC +6) Almaty, Dhaka, Colombo">TASHST-6;TASHDT</listitem>
+ <listitem name="(UTC +7) Bangkok, Hanoi, Jakarta">THAIST-7;THAIDT</listitem>
+ <listitem name="(UTC +8) Beijing, Singapore, Hong Kong">TAIST-8;TAIDT</listitem>
+ <listitem name="(UTC +9) Tokyo, Seoul, Yakutsk">JST-9;JSTDT</listitem>
+ <listitem name="(UTC +10) Eastern Australia, Guam">EET-10;EETDT</listitem>
+ <listitem name="(UTC +11) Vladivostok, Solomon Islands">MET-11;METDT</listitem>
+ <listitem name="(UTC +12) Auckland, Wellington, Fiji">NZST-12;NZDT</listitem>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row_dst_text_y%" />
+ <text>Do you use daylight savings time (DST)?</text>
+ <data variable="tw_time_zone_guidst" />
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row_offset_text_y%" placement="5" />
+ <text>Offset (usually 0): %tw_time_zone_guioffset%</text>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col1_medium_x%" y="%row_offset_medium_y%" />
+ <text>None</text>
+ <action function="set">tw_time_zone_guioffset=0</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col2_medium_x%" y="%row_offset_medium_y%" />
+ <text>15</text>
+ <action function="set">tw_time_zone_guioffset=15</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col3_medium_x%" y="%row_offset_medium_y%" />
+ <text>30</text>
+ <action function="set">tw_time_zone_guioffset=30</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%col4_medium_x%" y="%row_offset_medium_y%" />
+ <text>45</text>
+ <action function="set">tw_time_zone_guioffset=45</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%tz_set_y%" />
+ <text>Set Time Zone</text>
+ <action function="setguitimezone"></action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%tz_current_y%" placement="5" />
+ <text>Current Time Zone: %tw_time_zone%</text>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+ </page>
+
+ <page name="screen">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Screen Settings</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_screen_timeout_secs" op="=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ <text>Enable screen timeout.</text>
+ <image resource="checkbox_false" />
+ <action function="set">tw_screen_timeout_secs=60</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <font resource="font" color="%text_color%" />
+ <condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ <text>Enable screen timeout.</text>
+ <image resource="checkbox_true" />
+ <action function="set">tw_screen_timeout_secs=0</action>
+ </object>
+
+ <object type="slidervalue">
+ <conditions>
+ <condition var1="tw_screen_timeout_secs" op="!=" var2="0" />
+ <condition var1="tw_no_screen_timeout" op="!=" var2="1" />
+ </conditions>
+ <placement x="col1_x" y="%row4_text_y%" w="%slidervalue_w%" />
+ <text>Screen timeout in seconds:</text>
+ <data variable="tw_screen_timeout_secs" min="15" max="300" />
+ </object>
+
+ <object type="slidervalue">
+ <condition var1="tw_has_brightnesss_file" var2="1" />
+ <placement x="col1_x" y="%row8_text_y%" w="%slidervalue_w%" />
+ <text>Brightness: %tw_brightness_pct%%</text>
+ <data variable="tw_brightness_pct" min="10" max="100" />
+ <actions>
+ <action function="set">tw_brightness=%tw_brightness_max%</action>
+ <action function="compute">tw_brightness*%tw_brightness_pct%</action>
+ <action function="compute">tw_brightness/100</action>
+ <action function="setbrightness">%tw_brightness%</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="vibrate">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Vibration Settings :</text>
+ </object>
+
+ <object type="slidervalue">
+ <placement x="col1_x" y="%row1_text_y%" w="%slidervalue_w%" />
+ <text>Button Vibration:</text>
+ <data variable="tw_button_vibrate" min="0" max="300" />
+ </object>
+
+ <object type="slidervalue">
+ <placement x="col1_x" y="%row5_text_y%" w="%slidervalue_w%" />
+ <text>Keyboard Vibration:</text>
+ <data variable="tw_keyboard_vibrate" min="0" max="300" />
+ </object>
+
+ <object type="slidervalue">
+ <placement x="col1_x" y="%row9_text_y%" w="%slidervalue_w%" />
+ <text>Action Vibration:</text>
+ <data variable="tw_action_vibrate" min="0" max="500" />
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">settings</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="advanced">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Advanced</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Copy Log to SD</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=copylog</action>
+ <action function="set">tw_text1=Copy Log to SD Card?</action>
+ <action function="set">tw_action_text1=Copying Log to SD Card...</action>
+ <action function="set">tw_complete_text1=Log Copy Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Fix Permissions</text>
+ <action function="page">fixperms</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_allow_partition_sdcard" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Partition SD Card</text>
+ <action function="page">partsdcard</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>File Manager</text>
+ <action function="page">filemanagerlist</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>Terminal Command</text>
+ <action function="page">terminalfolder</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>Reload Theme</text>
+ <action function="reload"></action>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>ADB Sideload</text>
+ <action function="page">sideload</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_show_dumlock" var2="1" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>HTC Dumlock</text>
+ <action function="page">htcdumlock</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_has_injecttwrp" var2="1" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Re-Inject TWRP</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=reinjecttwrp</action>
+ <action function="set">tw_text1=Re-Inject TWRP?</action>
+ <action function="set">tw_action_text1=Re-Injecting TWRP...</action>
+ <action function="set">tw_complete_text1=TWRP Injection Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="partsdcard">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Partition SD Card</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text></text>
+ <image resource="minus_button" />
+ <action function="addsubtract">tw_sdext_size-128</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sd_plus_x%" y="%row1_y%" />
+ <text></text>
+ <image resource="plus_button" />
+ <action function="addsubtract">tw_sdext_size+128</action>
+ </object>
+
+ <object type="text">
+ <placement x="%sdext_text_x%" y="%sdext_text_y%" />
+ <text>EXT Size: %tw_sdext_size%</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%sdswap_button_y%" />
+ <text></text>
+ <image resource="minus_button" />
+ <action function="addsubtract">tw_swap_size-32</action>
+ </object>
+
+ <object type="button">
+ <placement x="%sd_plus_x%" y="%sdswap_button_y%" />
+ <text></text>
+ <image resource="plus_button" />
+ <action function="addsubtract">tw_swap_size+32</action>
+ </object>
+
+ <object type="text">
+ <placement x="%sdswap_text_x%" y="%sdswap_text_y%" />
+ <text>Swap Size: %tw_swap_size%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%sdfilesystem_text_y%" />
+ <text>File system: %tw_sdpart_file_system%</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%sdfilesystem_button_y%" />
+ <font resource="font" color="%button_text_color%" />
+ <text>EXT3</text>
+ <action function="set">tw_sdpart_file_system=ext3</action>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_sdext_disable_ext4" var2="0" />
+ <placement x="%col2_x%" y="%sdfilesystem_button_y%" />
+ <text>EXT4</text>
+ <image resource="main_button" />
+ <action function="set">tw_sdpart_file_system=ext4</action>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row10_text_y%" />
+ <text>You will lose all files on your SD card!</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row11_text_y%" />
+ <text>This action cannot be undone!</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Partition</text>
+ <actions>
+ <action function="set">tw_back=partsdcard</action>
+ <action function="set">tw_action=partitionsd</action>
+ <action function="set">tw_has_action2=1</action>
+ <action function="set">tw_action2=set</action>
+ <action function="set">tw_action2_param=tw_zip_location=/sdcard</action>
+ <action function="set">tw_action_text1=Partitioning SD Card...</action>
+ <action function="set">tw_action_text2=This will take a few minutes.</action>
+ <action function="set">tw_complete_text1=Partitioning Complete</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+ </page>
+
+ <page name="htcdumlock">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>HTC Dumlock</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row1_y%" />
+ <text>Restore Original Boot</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=htcdumlockrestoreboot</action>
+ <action function="set">tw_text1=Restore original boot image?</action>
+ <action function="set">tw_action_text1=Restoring Original Boot...</action>
+ <action function="set">tw_complete_text1=Restore Original Boot Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row1_y%" />
+ <text>Reflash Recovery</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=htcdumlockreflashrecovery</action>
+ <action function="set">tw_text1=Reflash recovery to boot?</action>
+ <action function="set">tw_action_text1=Flashing recovery to boot...</action>
+ <action function="set">tw_complete_text1=Recovery Flash to Boot Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Install HTC Dumlock</text>
+ <actions>
+ <action function="set">tw_back=htcdumlock</action>
+ <action function="set">tw_action=installhtcdumlock</action>
+ <action function="set">tw_text1=Install HTC dumlock files to ROM?</action>
+ <action function="set">tw_action_text1=Installing HTC Dumlock...</action>
+ <action function="set">tw_complete_text1=HTC Dumlock Install Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="page">confirm_action</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="lock">
+ <background color="#000000A0" />
+
+ <object type="image">
+ <image resource="unlock-icon" />
+ <placement x="%center_x%" y="%lock_y%" placement="4" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Unlock</text>
+ <action function="overlay"></action>
+ </object>
+ </page>
+
+ <page name="filemanagerlist">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>File Manager: Select a File or Folder</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row1_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_file_location1%</text>
+ <filter folders="1" files="1" />
+ <path name="tw_file_location1" default="/" />
+ <data name="tw_filename1" />
+ <selection name="tw_selection1" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <actions>
+ <action function="set">tw_fm_type=File</action>
+ <action function="set">tw_fm_isfolder=0</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_filename1" op="modified" />
+ <actions>
+ <action function="page">filemanageroptions</action>
+ </actions>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select</text>
+ <actions>
+ <action function="set">tw_filename1=tw_file_location1</action>
+ <action function="set">tw_fm_isfolder=1</action>
+ <action function="set">tw_fm_type=Folder</action>
+ <action function="page">filemanageroptions</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="filemanageroptions">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>%tw_fm_type% Selected:</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>%tw_filename1%</text>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="0" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Copy File</text>
+ <actions>
+ <action function="set">tw_filemanager_command=cp</action>
+ <action function="set">tw_fm_text1=Copying</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="1" />
+ <placement x="%col1_x%" y="%row2_y%" />
+ <text>Copy Folder</text>
+ <actions>
+ <action function="set">tw_filemanager_command=cd &quot;%tw_file_location1%&quot; &amp;&amp; cd .. &amp;&amp; cp -R</action>
+ <action function="set">tw_fm_text1=Copying</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row2_y%" />
+ <text>Move</text>
+ <actions>
+ <action function="set">tw_filemanager_command=mv</action>
+ <action function="set">tw_fm_text1=Moving</action>
+ <action function="page">choosedestinationfolder</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row3_y%" />
+ <text>chmod 755</text>
+ <actions>
+ <action function="set">tw_filemanager_command=chmod 755</action>
+ <action function="set">tw_fm_text1=chmod 755</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col2_x%" y="%row3_y%" />
+ <text>chmod</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=0000</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerchmod</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col1_x%" y="%row4_y%" />
+ <text>Delete</text>
+ <actions>
+ <action function="set">tw_filemanager_command=rm -rf</action>
+ <action function="set">tw_fm_text1=Deleting</action>
+ <action function="set">tw_fm_text2=</action>
+ <action function="set">tw_fm_text3=</action>
+ <action function="set">tw_include_text3=0</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="0" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Rename File</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=tw_selection1</action>
+ <action function="set">tw_fm_text1=Renaming</action>
+ <action function="set">tw_filemanager_command=mv</action>
+ <action function="page">filemanagerrenamefile</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <condition var1="tw_fm_isfolder" var2="1" />
+ <placement x="%col2_x%" y="%row4_y%" />
+ <text>Rename Folder</text>
+ <actions>
+ <action function="set">tw_filemanager_rename=tw_selection1</action>
+ <action function="set">tw_fm_text1=Renaming</action>
+ <action function="set">tw_filemanager_command=cd &quot;%tw_file_location1%&quot; &amp;&amp; cd .. &amp;&amp; mv</action>
+ <action function="page">filemanagerrenamefolder</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanagerlist</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="choosedestinationfolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>Browse to Destination &amp; Press Select</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row1_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_file_location2%</text>
+ <filter folders="1" files="0" />
+ <path name="tw_file_location2" default="/" />
+ <data name="tw_filename2" />
+ <selection name="tw_selection2" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select</text>
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=%tw_file_location2%</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="filemanagerrenamefile">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter a New %tw_fm_type% Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="1" maxlen="128" />
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=&quot;%tw_file_location1%/%tw_filemanager_rename%&quot;</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerrenamefolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter a New %tw_fm_type% Name</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="1" maxlen="128" />
+ <actions>
+ <action function="set">tw_fm_text2=to</action>
+ <action function="set">tw_fm_text3=%tw_filemanager_rename%</action>
+ <action function="set">tw_include_text3=1</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerchmod">
+ <object type="template" name="header" />
+
+ <object type="text" color="%text_color%">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <font resource="font" />
+ <text>Please Enter New Permissions</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_filemanager_rename%</text>
+ <data name="tw_filemanager_rename" />
+ <restrict minlen="3" maxlen="4" allow="0123456789" />
+ <actions>
+ <action function="set">tw_filemanager_command=chmod %tw_filemanager_rename%</action>
+ <action function="set">tw_fm_text1=chmod %tw_filemanager_rename%</action>
+ <action function="set">tw_back=filemanageroptions</action>
+ <action function="page">filemanagerconfirm</action>
+ </actions>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">filemanageroptions</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="filemanagerconfirm">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5"/>
+ <text>%tw_fm_text1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>%tw_filename1%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5"/>
+ <text>%tw_fm_text2%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5"/>
+ <text>%tw_fm_text3%</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row10_text_y%" placement="5"/>
+ <text>Press back button to cancel.</text>
+ </object>
+
+ <object type="slider">
+ <action function="page">filemanageracction</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">%tw_back%</action>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+ </page>
+
+ <page name="filemanageracction">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>%tw_fm_text1%</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_back=filemanagerlist</action>
+ <action function="set">tw_complete_text1=File Operation Complete</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_complete_text1=File Operation Complete</action>
+ <action function="page">action_complete</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_include_text3" var2="0" />
+ <actions>
+ <action function="cmd">%tw_filemanager_command% &quot;%tw_filename1%&quot;</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <condition var1="tw_include_text3" var2="1" />
+ <actions>
+ <action function="cmd">%tw_filemanager_command% &quot;%tw_filename1%&quot; &quot;%tw_fm_text3%&quot;</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="decrypt">
+ <object type="template" name="header" />
+
+ <object type="action">
+ <condition var1="tw_crypto_pwtype" var2="2" />
+ <action function="page">decrypt_pattern</action>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter Your Password</text>
+ </object>
+
+ <object type="input">
+ <placement x="%col1_x%" y="%row3_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_crypto_display%</text>
+ <data name="tw_crypto_password" mask="*" maskvariable="tw_crypto_display" />
+ <restrict minlen="1" maxlen="254" />
+ <actions>
+ <action function="page">trydecrypt</action>
+ </actions>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%" />
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>Password Failed, Please Try Again</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row2_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="decrypt_pattern">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Please Enter Your Pattern</text>
+ </object>
+
+ <object type="text">
+ <condition var1="tw_password_fail" var2="1" />
+ <font resource="font" color="%text_fail_color%"/>
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Pattern Failed, Please Try Again</text>
+ </object>
+
+ <object type="patternpassword">
+ <placement x="%pattern_x%" y="%pattern_y%" w="%pattern_width%" h="%pattern_width%" />
+ <dot color="%pattern_dot_color%" activecolor="%pattern_dot_color_active%" radius="%pattern_dot_radius%" />
+ <line color="%pattern_line_color%" width="%pattern_line_width%" />
+ <data name="tw_crypto_password"/>
+ <action function="page">trydecrypt</action>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row4_y%" />
+ <text>Cancel</text>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="trydecrypt">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>Trying Decryption with Your Password</text>
+ </object>
+
+ <object type="template" name="action_page_console" />
+
+ <object type="template" name="progress_bar" />
+
+ <object type="action">
+ <action function="decrypt"></action>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="!=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_password_fail=1</action>
+ <action function="page">decrypt</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <conditions>
+ <condition var1="tw_operation_state" var2="1" />
+ <condition var1="tw_operation_status" op="=" var2="0" />
+ </conditions>
+ <actions>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">main</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="terminalfolder">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>Browse to Starting Folder</text>
+ </object>
+
+ <object type="fileselector">
+ <placement x="%fileselector_x%" y="%row1_y%" w="%fileselector_width%" h="%fileselector_install_height%" />
+ <text>%tw_terminal_location%</text>
+ <filter folders="1" files="0" />
+ <path name="tw_terminal_location" default="/" />
+ <data name="tw_terminal" />
+ <selection name="tw_terminal_selection" />
+ </object>
+
+ <object type="template" name="sort_options" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <placement x="%filemanager_select_x%" y="%filemanager_select_y%" />
+ <text>Select</text>
+ <actions>
+ <action function="page">terminalcommand</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="terminalcommand">
+ <object type="template" name="header" />
+
+ <object type="console">
+ <placement x="%console_x%" y="0" w="%console_width%" h="%terminal_console_height%" />
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%terminal_text_y%" placement="0" />
+ <text>Starting Path: %tw_terminal_location%</text>
+ </object>
+
+ <object type="input">
+ <condition var1="tw_terminal_state" var2="0" />
+ <placement x="%col1_x%" y="%terminal_text_y%" w="%input_width%" h="%input_height%" placement="0" />
+ <text>%tw_terminal_command%</text>
+ <font resource="fixed" color="%text_color%" />
+ <data name="tw_terminal_command" />
+ <restrict minlen="1" />
+ <action function="terminalcommand">%tw_terminal_command%</action>
+ </object>
+
+ <object type="button" style="mediumbutton">
+ <condition var1="tw_terminal_state" var2="1" />
+ <placement x="%filemanager_select_x%" y="%terminal_button_y%" />
+ <text>KILL</text>
+ <action function="killterminal"></action>
+ </object>
+
+ <object type="template" name="keyboardtemplate" />
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">terminalfolder</action>
+ </object>
+ </page>
+
+ <page name="sideload">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>ADB Sideload</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>Wipe Dalvik Cache.</text>
+ <data variable="tw_wipe_dalvik" />
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Wipe Cache.</text>
+ <data variable="tw_wipe_cache" />
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Start Sideload</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=adbsideload</action>
+ <action function="set">tw_action_text1=ADB Sideload</action>
+ <action function="set">tw_action_text2=Usage: adb sideload filename.zip</action>
+ <action function="set">tw_complete_text1=ADB Sideload Complete</action>
+ <action function="set">tw_has_cancel=1</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="set">tw_cancel_action=adbsideloadcancel</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+ </page>
+
+ <page name="fixperms">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>Fix Permissions</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row2_text_y%" />
+ <text>Note: Fixing permissions is rarely needed.</text>
+ </object>
+
+ <object type="checkbox">
+ <placement x="%col1_x%" y="%row3_text_y%" />
+ <text>Also fix SELinux contexts</text>
+ <data variable="tw_fixperms_restorecon" />
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row4_text_y%" />
+ <text>Fixing SELinux contexts may cause</text>
+ </object>
+
+ <object type="text">
+ <placement x="%col1_x%" y="%row5_text_y%" />
+ <text>your device to not boot properly.</text>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Fix Permissions</text>
+ <actions>
+ <action function="set">tw_back=advanced</action>
+ <action function="set">tw_action=fixpermissions</action>
+ <action function="set">tw_action_text1=Fixing Permissions...</action>
+ <action function="set">tw_complete_text1=Fix Permissions Complete</action>
+ <action function="set">tw_slider_text=Swipe to Confirm</action>
+ <action function="set">tw_show_reboot=1</action>
+ <action function="page">action_page</action>
+ </actions>
+ </object>
+
+ <object type="action">
+ <touch key="home" />
+ <action function="page">main</action>
+ </object>
+
+ <object type="action">
+ <touch key="back" />
+ <action function="page">advanced</action>
+ </object>
+
+ <object type="template" name="footer" />
+ </page>
+
+ <page name="installsu">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5"/>
+ <text>Install SuperSU?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5"/>
+ <text>Your device does not appear to be rooted.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5"/>
+ <text>Install SuperSU now?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5"/>
+ <text>This will root your device.</text>
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row3_y%" />
+ <text>Do Not Install</text>
+ <action function="set">tw_page_done=1</action>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Install</text>
+ <actions>
+ <action function="set">tw_action=installsu</action>
+ <action function="set">tw_action_text1=Installing SuperSU</action>
+ <action function="set">tw_action_text2=</action>
+ <action function="page">singleaction_page</action>
+ </actions>
+ </object>
+ </page>
+
+ <page name="system_readonly">
+ <object type="template" name="header" />
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_header_y%" placement="5" />
+ <text>Keep System Read Only?</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row1_text_y%" placement="5" />
+ <text>TWRP can leave your system partition unmodified</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row2_text_y%" placement="5" />
+ <text>to make it easier for you to take official updates.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row3_text_y%" placement="5" />
+ <text>TWRP will be unable to prevent the stock ROM from</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row4_text_y%" placement="5" />
+ <text>replacing TWRP and will not offer to root your device.</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row5_text_y%" placement="5" />
+ <text>Installing zips or performing adb operations may still</text>
+ </object>
+
+ <object type="text">
+ <placement x="%center_x%" y="%row6_text_y%" placement="5" />
+ <text>modify the system partition.</text>
+ </object>
+
+ <object type="checkbox">
+ <condition var1="tw_is_encrypted" var2="0" />
+ <placement x="%col1_x%" y="%row7_text_y%" />
+ <text>Never show this screen during boot again</text>
+ <data variable="tw_never_show_system_ro_page" />
+ </object>
+
+ <object type="button">
+ <placement x="%col_center_x%" y="%row9_text_y%" />
+ <text>Keep Read Only</text>
+ <actions>
+ <action function="mountsystemtoggle">1</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+
+ <object type="slider">
+ <text>Swipe to Allow Modifications</text>
+ <actions>
+ <action function="mountsystemtoggle">0</action>
+ <action function="set">tw_page_done=1</action>
+ <action function="page">%tw_back%</action>
+ </actions>
+ </object>
+ </page>
+ </pages>
+</recovery>
diff --git a/gui/fileselector.cpp b/gui/fileselector.cpp
new file mode 100644
index 000000000..a97ff34b1
--- /dev/null
+++ b/gui/fileselector.cpp
@@ -0,0 +1,382 @@
+/*
+ Copyright 2012 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <sys/stat.h>
+#include <dirent.h>
+#include <algorithm>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../data.hpp"
+#include "../twrp-functions.hpp"
+
+#define TW_FILESELECTOR_UP_A_LEVEL "(Up A Level)"
+
+int GUIFileSelector::mSortOrder = 0;
+
+GUIFileSelector::GUIFileSelector(xml_node<>* node) : GUIScrollList(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ mFolderIcon = mFileIcon = NULL;
+ mShowFolders = mShowFiles = mShowNavFolders = 1;
+ mUpdate = 0;
+ mPathVar = "cwd";
+ updateFileList = false;
+
+ // Load filter for filtering files (e.g. *.zip for only zips)
+ child = FindNode(node, "filter");
+ if (child) {
+ attr = child->first_attribute("extn");
+ if (attr)
+ mExtn = attr->value();
+ attr = child->first_attribute("folders");
+ if (attr)
+ mShowFolders = atoi(attr->value());
+ attr = child->first_attribute("files");
+ if (attr)
+ mShowFiles = atoi(attr->value());
+ attr = child->first_attribute("nav");
+ if (attr)
+ mShowNavFolders = atoi(attr->value());
+ }
+
+ // Handle the path variable
+ child = FindNode(node, "path");
+ if (child) {
+ attr = child->first_attribute("name");
+ if (attr)
+ mPathVar = attr->value();
+ attr = child->first_attribute("default");
+ if (attr) {
+ mPathDefault = attr->value();
+ DataManager::SetValue(mPathVar, attr->value());
+ }
+ }
+
+ // Handle the result variable
+ child = FindNode(node, "data");
+ if (child) {
+ attr = child->first_attribute("name");
+ if (attr)
+ mVariable = attr->value();
+ attr = child->first_attribute("default");
+ if (attr)
+ DataManager::SetValue(mVariable, attr->value());
+ }
+
+ // Handle the sort variable
+ child = FindNode(node, "sort");
+ if (child) {
+ attr = child->first_attribute("name");
+ if (attr)
+ mSortVariable = attr->value();
+ attr = child->first_attribute("default");
+ if (attr)
+ DataManager::SetValue(mSortVariable, attr->value());
+
+ DataManager::GetValue(mSortVariable, mSortOrder);
+ }
+
+ // Handle the selection variable
+ child = FindNode(node, "selection");
+ if (child && (attr = child->first_attribute("name")))
+ mSelection = attr->value();
+ else
+ mSelection = "0";
+
+ // Get folder and file icons if present
+ child = FindNode(node, "icon");
+ if (child) {
+ mFolderIcon = LoadAttrImage(child, "folder");
+ mFileIcon = LoadAttrImage(child, "file");
+ }
+ int iconWidth = std::max(mFolderIcon->GetWidth(), mFileIcon->GetWidth());
+ int iconHeight = std::max(mFolderIcon->GetHeight(), mFileIcon->GetHeight());
+ SetMaxIconSize(iconWidth, iconHeight);
+
+ // Fetch the file/folder list
+ std::string value;
+ DataManager::GetValue(mPathVar, value);
+ GetFileList(value);
+}
+
+GUIFileSelector::~GUIFileSelector()
+{
+}
+
+int GUIFileSelector::Update(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ GUIScrollList::Update();
+
+ // Update the file list if needed
+ if (updateFileList) {
+ string value;
+ DataManager::GetValue(mPathVar, value);
+ if (GetFileList(value) == 0) {
+ updateFileList = false;
+ mUpdate = 1;
+ } else
+ return 0;
+ }
+
+ if (mUpdate) {
+ mUpdate = 0;
+ if (Render() == 0)
+ return 2;
+ }
+ return 0;
+}
+
+int GUIFileSelector::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIScrollList::NotifyVarChange(varName, value);
+
+ if(!isConditionTrue())
+ return 0;
+
+ if (varName.empty()) {
+ // Always clear the data variable so we know to use it
+ DataManager::SetValue(mVariable, "");
+ }
+ if (varName == mPathVar || varName == mSortVariable) {
+ if (varName == mSortVariable) {
+ DataManager::GetValue(mSortVariable, mSortOrder);
+ } else {
+ // Reset the list to the top
+ SetVisibleListLocation(0);
+ if (value.empty())
+ DataManager::SetValue(mPathVar, mPathDefault);
+ }
+ updateFileList = true;
+ mUpdate = 1;
+ return 0;
+ }
+ return 0;
+}
+
+bool GUIFileSelector::fileSort(FileData d1, FileData d2)
+{
+ if (d1.fileName == ".")
+ return -1;
+ if (d2.fileName == ".")
+ return 0;
+ if (d1.fileName == TW_FILESELECTOR_UP_A_LEVEL)
+ return -1;
+ if (d2.fileName == TW_FILESELECTOR_UP_A_LEVEL)
+ return 0;
+
+ switch (mSortOrder) {
+ case 3: // by size largest first
+ if (d1.fileSize == d2.fileSize || d1.fileType == DT_DIR) // some directories report a different size than others - but this is not the size of the files inside the directory, so we just sort by name on directories
+ return (strcasecmp(d1.fileName.c_str(), d2.fileName.c_str()) < 0);
+ return d1.fileSize < d2.fileSize;
+ case -3: // by size smallest first
+ if (d1.fileSize == d2.fileSize || d1.fileType == DT_DIR) // some directories report a different size than others - but this is not the size of the files inside the directory, so we just sort by name on directories
+ return (strcasecmp(d1.fileName.c_str(), d2.fileName.c_str()) > 0);
+ return d1.fileSize > d2.fileSize;
+ case 2: // by last modified date newest first
+ if (d1.lastModified == d2.lastModified)
+ return (strcasecmp(d1.fileName.c_str(), d2.fileName.c_str()) < 0);
+ return d1.lastModified < d2.lastModified;
+ case -2: // by date oldest first
+ if (d1.lastModified == d2.lastModified)
+ return (strcasecmp(d1.fileName.c_str(), d2.fileName.c_str()) > 0);
+ return d1.lastModified > d2.lastModified;
+ case -1: // by name descending
+ return (strcasecmp(d1.fileName.c_str(), d2.fileName.c_str()) > 0);
+ default: // should be a 1 - sort by name ascending
+ return (strcasecmp(d1.fileName.c_str(), d2.fileName.c_str()) < 0);
+ }
+ return 0;
+}
+
+int GUIFileSelector::GetFileList(const std::string folder)
+{
+ DIR* d;
+ struct dirent* de;
+ struct stat st;
+
+ // Clear all data
+ mFolderList.clear();
+ mFileList.clear();
+
+ d = opendir(folder.c_str());
+ if (d == NULL) {
+ LOGINFO("Unable to open '%s'\n", folder.c_str());
+ if (folder != "/" && (mShowNavFolders != 0 || mShowFiles != 0)) {
+ size_t found;
+ found = folder.find_last_of('/');
+ if (found != string::npos) {
+ string new_folder = folder.substr(0, found);
+
+ if (new_folder.length() < 2)
+ new_folder = "/";
+ DataManager::SetValue(mPathVar, new_folder);
+ }
+ }
+ return -1;
+ }
+
+ while ((de = readdir(d)) != NULL) {
+ FileData data;
+
+ data.fileName = de->d_name;
+ if (data.fileName == ".")
+ continue;
+ if (data.fileName == ".." && folder == "/")
+ continue;
+ if (data.fileName == "..") {
+ data.fileName = TW_FILESELECTOR_UP_A_LEVEL;
+ data.fileType = DT_DIR;
+ } else {
+ data.fileType = de->d_type;
+ }
+
+ std::string path = folder + "/" + data.fileName;
+ stat(path.c_str(), &st);
+ data.protection = st.st_mode;
+ data.userId = st.st_uid;
+ data.groupId = st.st_gid;
+ data.fileSize = st.st_size;
+ data.lastAccess = st.st_atime;
+ data.lastModified = st.st_mtime;
+ data.lastStatChange = st.st_ctime;
+
+ if (data.fileType == DT_UNKNOWN) {
+ data.fileType = TWFunc::Get_D_Type_From_Stat(path);
+ }
+ if (data.fileType == DT_DIR) {
+ if (mShowNavFolders || (data.fileName != "." && data.fileName != TW_FILESELECTOR_UP_A_LEVEL))
+ mFolderList.push_back(data);
+ } else if (data.fileType == DT_REG || data.fileType == DT_LNK || data.fileType == DT_BLK) {
+ if (mExtn.empty() || (data.fileName.length() > mExtn.length() && data.fileName.substr(data.fileName.length() - mExtn.length()) == mExtn)) {
+ mFileList.push_back(data);
+ }
+ }
+ }
+ closedir(d);
+
+ std::sort(mFolderList.begin(), mFolderList.end(), fileSort);
+ std::sort(mFileList.begin(), mFileList.end(), fileSort);
+
+ return 0;
+}
+
+void GUIFileSelector::SetPageFocus(int inFocus)
+{
+ GUIScrollList::SetPageFocus(inFocus);
+ if (inFocus) {
+ std::string value;
+ DataManager::GetValue(mPathVar, value);
+ if (value.empty())
+ DataManager::SetValue(mPathVar, mPathDefault);
+ updateFileList = true;
+ mUpdate = 1;
+ }
+}
+
+size_t GUIFileSelector::GetItemCount()
+{
+ size_t folderSize = mShowFolders ? mFolderList.size() : 0;
+ size_t fileSize = mShowFiles ? mFileList.size() : 0;
+ return folderSize + fileSize;
+}
+
+void GUIFileSelector::RenderItem(size_t itemindex, int yPos, bool selected)
+{
+ size_t folderSize = mShowFolders ? mFolderList.size() : 0;
+ size_t fileSize = mShowFiles ? mFileList.size() : 0;
+
+ ImageResource* icon;
+ std::string text;
+
+ if (itemindex < folderSize) {
+ text = mFolderList.at(itemindex).fileName;
+ icon = mFolderIcon;
+ } else {
+ text = mFileList.at(itemindex - folderSize).fileName;
+ icon = mFileIcon;
+ }
+
+ RenderStdItem(yPos, selected, icon, text.c_str());
+}
+
+void GUIFileSelector::NotifySelect(size_t item_selected)
+{
+ size_t folderSize = mShowFolders ? mFolderList.size() : 0;
+ size_t fileSize = mShowFiles ? mFileList.size() : 0;
+
+ if (item_selected < folderSize + fileSize) {
+ // We've selected an item!
+ std::string str;
+ if (item_selected < folderSize) {
+ std::string cwd;
+
+ str = mFolderList.at(item_selected).fileName;
+ if (mSelection != "0")
+ DataManager::SetValue(mSelection, str);
+ DataManager::GetValue(mPathVar, cwd);
+
+ // Ignore requests to do nothing
+ if (str == ".") return;
+ if (str == TW_FILESELECTOR_UP_A_LEVEL) {
+ if (cwd != "/") {
+ size_t found;
+ found = cwd.find_last_of('/');
+ cwd = cwd.substr(0,found);
+
+ if (cwd.length() < 2) cwd = "/";
+ }
+ } else {
+ // Add a slash if we're not the root folder
+ if (cwd != "/") cwd += "/";
+ cwd += str;
+ }
+
+ if (mShowNavFolders == 0 && mShowFiles == 0) {
+ // nav folders and files are disabled, this is probably the restore list and we need to save chosen location to mVariable instead of mPathVar
+ DataManager::SetValue(mVariable, cwd);
+ } else {
+ // We are changing paths, so we need to set mPathVar
+ DataManager::SetValue(mPathVar, cwd);
+ }
+ } else if (!mVariable.empty()) {
+ str = mFileList.at(item_selected - folderSize).fileName;
+ if (mSelection != "0")
+ DataManager::SetValue(mSelection, str);
+
+ std::string cwd;
+ DataManager::GetValue(mPathVar, cwd);
+ if (cwd != "/")
+ cwd += "/";
+ DataManager::SetValue(mVariable, cwd + str);
+ }
+ }
+ mUpdate = 1;
+}
diff --git a/gui/fill.cpp b/gui/fill.cpp
new file mode 100644
index 000000000..b315cd08a
--- /dev/null
+++ b/gui/fill.cpp
@@ -0,0 +1,52 @@
+// fill.cpp - GUIFill object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUIFill::GUIFill(xml_node<>* node) : GUIObject(node)
+{
+ bool has_color = false;
+ mColor = LoadAttrColor(node, "color", &has_color);
+ if (!has_color) {
+ LOGERR("No color specified for fill\n");
+ return;
+ }
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
+
+ return;
+}
+
+int GUIFill::Render(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ gr_color(mColor.red, mColor.green, mColor.blue, mColor.alpha);
+ gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
+ return 0;
+}
+
diff --git a/gui/gui.cpp b/gui/gui.cpp
new file mode 100644
index 000000000..ebd70534c
--- /dev/null
+++ b/gui/gui.cpp
@@ -0,0 +1,1051 @@
+/*
+ Copyright 2012 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <linux/input.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+extern "C"
+{
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+#include <pixelflinger/pixelflinger.h>
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../data.hpp"
+#include "../variables.h"
+#include "../partitions.hpp"
+#include "../twrp-functions.hpp"
+#include "../openrecoveryscript.hpp"
+#include "../orscmd/orscmd.h"
+#include "blanktimer.hpp"
+#include "../tw_atomic.hpp"
+
+// Enable to print render time of each frame to the log file
+//#define PRINT_RENDER_TIME 1
+
+#ifdef _EVENT_LOGGING
+#define LOGEVENT(...) LOGERR(__VA_ARGS__)
+#else
+#define LOGEVENT(...) do {} while (0)
+#endif
+
+const static int CURTAIN_FADE = 32;
+
+using namespace rapidxml;
+
+// Global values
+static gr_surface gCurtain = NULL;
+static int gGuiInitialized = 0;
+static TWAtomicInt gGuiConsoleRunning;
+static TWAtomicInt gGuiConsoleTerminate;
+static TWAtomicInt gForceRender;
+const int gNoAnimation = 1;
+blanktimer blankTimer;
+int ors_read_fd = -1;
+static float scale_theme_w = 1;
+static float scale_theme_h = 1;
+
+// Needed by pages.cpp too
+int gGuiRunning = 0;
+
+static int gRecorder = -1;
+
+extern "C" void gr_write_frame_to_file(int fd);
+
+void flip(void)
+{
+ if (gRecorder != -1)
+ {
+ timespec time;
+ clock_gettime(CLOCK_MONOTONIC, &time);
+ write(gRecorder, &time, sizeof(timespec));
+ gr_write_frame_to_file(gRecorder);
+ }
+ gr_flip();
+}
+
+void rapidxml::parse_error_handler(const char *what, void *where)
+{
+ fprintf(stderr, "Parser error: %s\n", what);
+ fprintf(stderr, " Start of string: %s\n",(char *) where);
+ LOGERR("Error parsing XML file.\n");
+ //abort();
+}
+
+static void curtainSet()
+{
+ gr_color(0, 0, 0, 255);
+ gr_fill(0, 0, gr_fb_width(), gr_fb_height());
+ gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain), gr_get_height(gCurtain), TW_X_OFFSET, TW_Y_OFFSET);
+ gr_flip();
+}
+
+static void curtainRaise(gr_surface surface)
+{
+ int sy = 0;
+ int h = gr_get_height(gCurtain) - 1;
+ int w = gr_get_width(gCurtain);
+ int fy = 1;
+
+ int msw = gr_get_width(surface);
+ int msh = gr_get_height(surface);
+ int CURTAIN_RATE = msh / 30;
+
+ if (gNoAnimation == 0)
+ {
+ for (; h > 0; h -= CURTAIN_RATE, sy += CURTAIN_RATE, fy += CURTAIN_RATE)
+ {
+ gr_blit(surface, 0, 0, msw, msh, 0, 0);
+ gr_blit(gCurtain, 0, sy, w, h, 0, 0);
+ gr_flip();
+ }
+ }
+ gr_blit(surface, 0, 0, msw, msh, 0, 0);
+ flip();
+}
+
+void curtainClose()
+{
+#if 0
+ int w = gr_get_width(gCurtain);
+ int h = 1;
+ int sy = gr_get_height(gCurtain) - 1;
+ int fbh = gr_fb_height();
+ int CURTAIN_RATE = fbh / 30;
+
+ if (gNoAnimation == 0)
+ {
+ for (; h < fbh; h += CURTAIN_RATE, sy -= CURTAIN_RATE)
+ {
+ gr_blit(gCurtain, 0, sy, w, h, 0, 0);
+ gr_flip();
+ }
+ gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain),
+ gr_get_height(gCurtain), 0, 0);
+ gr_flip();
+
+ if (gRecorder != -1)
+ close(gRecorder);
+
+ int fade;
+ for (fade = 16; fade < 255; fade += CURTAIN_FADE)
+ {
+ gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain),
+ gr_get_height(gCurtain), 0, 0);
+ gr_color(0, 0, 0, fade);
+ gr_fill(0, 0, gr_fb_width(), gr_fb_height());
+ gr_flip();
+ }
+ gr_color(0, 0, 0, 255);
+ gr_fill(0, 0, gr_fb_width(), gr_fb_height());
+ gr_flip();
+ }
+#else
+ gr_blit(gCurtain, 0, 0, gr_get_width(gCurtain), gr_get_height(gCurtain), 0, 0);
+ gr_flip();
+#endif
+}
+
+class InputHandler
+{
+public:
+ void init()
+ {
+ // these might be read from DataManager in the future
+ touch_hold_ms = 500;
+ touch_repeat_ms = 100;
+ key_hold_ms = 500;
+ key_repeat_ms = 100;
+ touch_status = TS_NONE;
+ key_status = KS_NONE;
+ state = AS_NO_ACTION;
+ x = y = 0;
+
+#ifndef TW_NO_SCREEN_TIMEOUT
+ {
+ string seconds;
+ DataManager::GetValue("tw_screen_timeout_secs", seconds);
+ blankTimer.setTime(atoi(seconds.c_str()));
+ blankTimer.resetTimerAndUnblank();
+ }
+#else
+ LOGINFO("Skipping screen timeout: TW_NO_SCREEN_TIMEOUT is set\n");
+#endif
+ }
+
+ // process input events. returns true if any event was received.
+ bool processInput(int timeout_ms);
+
+ void handleDrag();
+
+private:
+ // timeouts for touch/key hold and repeat
+ int touch_hold_ms;
+ int touch_repeat_ms;
+ int key_hold_ms;
+ int key_repeat_ms;
+
+ enum touch_status_enum {
+ TS_NONE = 0,
+ TS_TOUCH_AND_HOLD = 1,
+ TS_TOUCH_REPEAT = 2,
+ };
+
+ enum key_status_enum {
+ KS_NONE = 0,
+ KS_KEY_PRESSED = 1,
+ KS_KEY_REPEAT = 2,
+ };
+
+ enum action_state_enum {
+ AS_IN_ACTION_AREA = 0, // we've touched a spot with an action
+ AS_NO_ACTION = 1, // we've touched in an empty area (no action) and ignore remaining events until touch release
+ };
+ touch_status_enum touch_status;
+ key_status_enum key_status;
+ action_state_enum state;
+ int x, y; // x and y coordinates of last touch
+ struct timeval touchStart; // used to track time for long press / key repeat
+
+ void processHoldAndRepeat();
+ void process_EV_REL(input_event& ev);
+ void process_EV_ABS(input_event& ev);
+ void process_EV_KEY(input_event& ev);
+
+ void doTouchStart();
+};
+
+InputHandler input_handler;
+
+
+bool InputHandler::processInput(int timeout_ms)
+{
+ input_event ev;
+ int ret = ev_get(&ev, timeout_ms);
+
+ if (ret < 0)
+ {
+ // This path means that we did not get any new touch data, but
+ // we do not get new touch data if you press and hold on either
+ // the screen or on a keyboard key or mouse button
+ if (touch_status || key_status)
+ processHoldAndRepeat();
+ return (ret != -2); // -2 means no more events in the queue
+ }
+
+ switch (ev.type)
+ {
+ case EV_ABS:
+ process_EV_ABS(ev);
+ break;
+
+ case EV_REL:
+ process_EV_REL(ev);
+ break;
+
+ case EV_KEY:
+ process_EV_KEY(ev);
+ break;
+ }
+
+ blankTimer.resetTimerAndUnblank();
+ return true; // we got an event, so there might be more in the queue
+}
+
+void InputHandler::processHoldAndRepeat()
+{
+ HardwareKeyboard *kb = PageManager::GetHardwareKeyboard();
+
+ // touch and key repeat section
+ struct timeval curTime;
+ gettimeofday(&curTime, NULL);
+ long seconds = curTime.tv_sec - touchStart.tv_sec;
+ long useconds = curTime.tv_usec - touchStart.tv_usec;
+ long mtime = ((seconds) * 1000 + useconds / 1000.0) + 0.5;
+
+ if (touch_status == TS_TOUCH_AND_HOLD && mtime > touch_hold_ms)
+ {
+ touch_status = TS_TOUCH_REPEAT;
+ gettimeofday(&touchStart, NULL);
+ LOGEVENT("TOUCH_HOLD: %d,%d\n", x, y);
+ PageManager::NotifyTouch(TOUCH_HOLD, x, y);
+ }
+ else if (touch_status == TS_TOUCH_REPEAT && mtime > touch_repeat_ms)
+ {
+ LOGEVENT("TOUCH_REPEAT: %d,%d\n", x, y);
+ gettimeofday(&touchStart, NULL);
+ PageManager::NotifyTouch(TOUCH_REPEAT, x, y);
+ }
+ else if (key_status == KS_KEY_PRESSED && mtime > key_hold_ms)
+ {
+ LOGEVENT("KEY_HOLD: %d,%d\n", x, y);
+ gettimeofday(&touchStart, NULL);
+ key_status = KS_KEY_REPEAT;
+ kb->KeyRepeat();
+ }
+ else if (key_status == KS_KEY_REPEAT && mtime > key_repeat_ms)
+ {
+ LOGEVENT("KEY_REPEAT: %d,%d\n", x, y);
+ gettimeofday(&touchStart, NULL);
+ kb->KeyRepeat();
+ }
+}
+
+void InputHandler::doTouchStart()
+{
+ LOGEVENT("TOUCH_START: %d,%d\n", x, y);
+ if (PageManager::NotifyTouch(TOUCH_START, x, y) > 0)
+ state = AS_NO_ACTION;
+ else
+ state = AS_IN_ACTION_AREA;
+ touch_status = TS_TOUCH_AND_HOLD;
+ gettimeofday(&touchStart, NULL);
+}
+
+void InputHandler::process_EV_ABS(input_event& ev)
+{
+ x = ev.value >> 16;
+ y = ev.value & 0xFFFF;
+
+ if (ev.code == 0)
+ {
+#ifndef TW_USE_KEY_CODE_TOUCH_SYNC
+ if (state == AS_IN_ACTION_AREA)
+ {
+ LOGEVENT("TOUCH_RELEASE: %d,%d\n", x, y);
+ PageManager::NotifyTouch(TOUCH_RELEASE, x, y);
+ }
+ touch_status = TS_NONE;
+#endif
+ }
+ else
+ {
+ if (!touch_status)
+ {
+#ifndef TW_USE_KEY_CODE_TOUCH_SYNC
+ doTouchStart();
+#endif
+ }
+ else
+ {
+ if (state == AS_IN_ACTION_AREA)
+ {
+ LOGEVENT("TOUCH_DRAG: %d,%d\n", x, y);
+ }
+ }
+ }
+}
+
+void InputHandler::process_EV_KEY(input_event& ev)
+{
+ HardwareKeyboard *kb = PageManager::GetHardwareKeyboard();
+
+ // Handle key-press here
+ LOGEVENT("TOUCH_KEY: %d\n", ev.code);
+ // Left mouse button is treated as a touch
+ if(ev.code == BTN_LEFT)
+ {
+ MouseCursor *cursor = PageManager::GetMouseCursor();
+ if(ev.value == 1)
+ {
+ cursor->GetPos(x, y);
+ doTouchStart();
+ }
+ else if(touch_status)
+ {
+ // Left mouse button was previously pressed and now is
+ // being released so send a TOUCH_RELEASE
+ if (state == AS_IN_ACTION_AREA)
+ {
+ cursor->GetPos(x, y);
+
+ LOGEVENT("Mouse TOUCH_RELEASE: %d,%d\n", x, y);
+ PageManager::NotifyTouch(TOUCH_RELEASE, x, y);
+ }
+ touch_status = TS_NONE;
+ }
+ }
+ // side mouse button, often used for "back" function
+ else if(ev.code == BTN_SIDE)
+ {
+ if(ev.value == 1)
+ kb->KeyDown(KEY_BACK);
+ else
+ kb->KeyUp(KEY_BACK);
+ } else if (ev.value != 0) {
+ // This is a key press
+#ifdef TW_USE_KEY_CODE_TOUCH_SYNC
+ if (ev.code == TW_USE_KEY_CODE_TOUCH_SYNC) {
+ LOGEVENT("key code %i key press == touch start %i %i\n", TW_USE_KEY_CODE_TOUCH_SYNC, x, y);
+ doTouchStart();
+ return;
+ }
+#endif
+ if (kb->KeyDown(ev.code)) {
+ // Key repeat is enabled for this key
+ key_status = KS_KEY_PRESSED;
+ touch_status = TS_NONE;
+ gettimeofday(&touchStart, NULL);
+ } else {
+ key_status = KS_NONE;
+ touch_status = TS_NONE;
+ }
+ } else {
+ // This is a key release
+ kb->KeyUp(ev.code);
+ key_status = KS_NONE;
+ touch_status = TS_NONE;
+#ifdef TW_USE_KEY_CODE_TOUCH_SYNC
+ if (ev.code == TW_USE_KEY_CODE_TOUCH_SYNC) {
+ LOGEVENT("key code %i key release == touch release %i %i\n", TW_USE_KEY_CODE_TOUCH_SYNC, x, y);
+ PageManager::NotifyTouch(TOUCH_RELEASE, x, y);
+ }
+#endif
+ }
+}
+
+void InputHandler::process_EV_REL(input_event& ev)
+{
+ // Mouse movement
+ MouseCursor *cursor = PageManager::GetMouseCursor();
+ LOGEVENT("EV_REL %d %d\n", ev.code, ev.value);
+ if(ev.code == REL_X)
+ cursor->Move(ev.value, 0);
+ else if(ev.code == REL_Y)
+ cursor->Move(0, ev.value);
+
+ if(touch_status) {
+ cursor->GetPos(x, y);
+ LOGEVENT("Mouse TOUCH_DRAG: %d, %d\n", x, y);
+ key_status = KS_NONE;
+ }
+}
+
+void InputHandler::handleDrag()
+{
+ // This allows us to only send one NotifyTouch event per render
+ // cycle to reduce overhead and perceived input latency.
+ static int prevx = 0, prevy = 0; // these track where the last drag notice was so that we don't send duplicate drag notices
+ if (touch_status && (x != prevx || y != prevy)) {
+ prevx = x;
+ prevy = y;
+ if (PageManager::NotifyTouch(TOUCH_DRAG, x, y) > 0)
+ state = AS_NO_ACTION;
+ else
+ state = AS_IN_ACTION_AREA;
+ }
+}
+
+static void setup_ors_command()
+{
+ ors_read_fd = -1;
+
+ unlink(ORS_INPUT_FILE);
+ if (mkfifo(ORS_INPUT_FILE, 06660) != 0) {
+ LOGINFO("Unable to mkfifo %s\n", ORS_INPUT_FILE);
+ return;
+ }
+ unlink(ORS_OUTPUT_FILE);
+ if (mkfifo(ORS_OUTPUT_FILE, 06666) != 0) {
+ LOGINFO("Unable to mkfifo %s\n", ORS_OUTPUT_FILE);
+ unlink(ORS_INPUT_FILE);
+ return;
+ }
+
+ ors_read_fd = open(ORS_INPUT_FILE, O_RDONLY | O_NONBLOCK);
+ if (ors_read_fd < 0) {
+ LOGINFO("Unable to open %s\n", ORS_INPUT_FILE);
+ unlink(ORS_INPUT_FILE);
+ unlink(ORS_OUTPUT_FILE);
+ }
+}
+
+static void ors_command_read()
+{
+ FILE* orsout;
+ char command[1024], result[512];
+ int set_page_done = 0, read_ret = 0;
+
+ if ((read_ret = read(ors_read_fd, &command, sizeof(command))) > 0) {
+ command[1022] = '\n';
+ command[1023] = '\0';
+ LOGINFO("Command '%s' received\n", command);
+ orsout = fopen(ORS_OUTPUT_FILE, "w");
+ if (!orsout) {
+ close(ors_read_fd);
+ ors_read_fd = -1;
+ LOGINFO("Unable to fopen %s\n", ORS_OUTPUT_FILE);
+ unlink(ORS_INPUT_FILE);
+ unlink(ORS_OUTPUT_FILE);
+ return;
+ }
+ if (DataManager::GetIntValue("tw_busy") != 0) {
+ strcpy(result, "Failed, operation in progress\n");
+ fprintf(orsout, "%s", result);
+ LOGINFO("Command cannot be performed, operation in progress.\n");
+ } else {
+ if (gui_console_only() == 0) {
+ LOGINFO("Console started successfully\n");
+ gui_set_FILE(orsout);
+ if (strlen(command) > 11 && strncmp(command, "runscript", 9) == 0) {
+ char* filename = command + 11;
+ if (OpenRecoveryScript::copy_script_file(filename) == 0) {
+ LOGERR("Unable to copy script file\n");
+ } else {
+ OpenRecoveryScript::run_script_file();
+ }
+ } else if (strlen(command) > 5 && strncmp(command, "get", 3) == 0) {
+ char* varname = command + 4;
+ string temp;
+ DataManager::GetValue(varname, temp);
+ gui_print("%s = %s\n", varname, temp.c_str());
+ } else if (strlen(command) > 9 && strncmp(command, "decrypt", 7) == 0) {
+ char* pass = command + 8;
+ gui_print("Attempting to decrypt data partition via command line.\n");
+ if (PartitionManager.Decrypt_Device(pass) == 0) {
+ set_page_done = 1;
+ }
+ } else if (OpenRecoveryScript::Insert_ORS_Command(command)) {
+ OpenRecoveryScript::run_script_file();
+ }
+ gui_set_FILE(NULL);
+ gGuiConsoleTerminate.set_value(1);
+ }
+ }
+ fclose(orsout);
+ LOGINFO("Done reading ORS command from command line\n");
+ if (set_page_done) {
+ DataManager::SetValue("tw_page_done", 1);
+ } else {
+ // The select function will return ready to read and the
+ // read function will return errno 19 no such device unless
+ // we set everything up all over again.
+ close(ors_read_fd);
+ setup_ors_command();
+ }
+ } else {
+ LOGINFO("ORS command line read returned an error: %i, %i, %s\n", read_ret, errno, strerror(errno));
+ }
+ return;
+}
+
+// This special function will return immediately the first time, but then
+// always returns 1/30th of a second (or immediately if called later) from
+// the last time it was called
+static void loopTimer(int input_timeout_ms)
+{
+ static timespec lastCall;
+ static int initialized = 0;
+
+ if (!initialized)
+ {
+ clock_gettime(CLOCK_MONOTONIC, &lastCall);
+ initialized = 1;
+ return;
+ }
+
+ do
+ {
+ bool got_event = input_handler.processInput(input_timeout_ms); // get inputs but don't send drag notices
+ timespec curTime;
+ clock_gettime(CLOCK_MONOTONIC, &curTime);
+
+ timespec diff = TWFunc::timespec_diff(lastCall, curTime);
+
+ // This is really 2 or 30 times per second
+ // As long as we get events, increase the timeout so we can catch up with input
+ long timeout = got_event ? 500000000 : 33333333;
+
+ if (diff.tv_sec || diff.tv_nsec > timeout)
+ {
+ // int32_t input_time = TWFunc::timespec_diff_ms(lastCall, curTime);
+ // LOGINFO("loopTimer(): %u ms, count: %u\n", input_time, count);
+
+ lastCall = curTime;
+ input_handler.handleDrag(); // send only drag notices if needed
+ return;
+ }
+
+ // We need to sleep some period time microseconds
+ //unsigned int sleepTime = 33333 -(diff.tv_nsec / 1000);
+ //usleep(sleepTime); // removed so we can scan for input
+ input_timeout_ms = 0;
+ } while (1);
+}
+
+static int runPages(const char *page_name, const int stop_on_page_done)
+{
+ DataManager::SetValue("tw_page_done", 0);
+ DataManager::SetValue("tw_gui_done", 0);
+
+ if (page_name)
+ gui_changePage(page_name);
+
+ // Raise the curtain
+ if (gCurtain != NULL)
+ {
+ gr_surface surface;
+
+ PageManager::Render();
+ gr_get_surface(&surface);
+ curtainRaise(surface);
+ gr_free_surface(surface);
+ }
+
+ gGuiRunning = 1;
+
+ DataManager::SetValue("tw_loaded", 1);
+
+#ifndef TW_OEM_BUILD
+ struct timeval timeout;
+ fd_set fdset;
+ int has_data = 0;
+#endif
+
+ int input_timeout_ms = 0;
+ int idle_frames = 0;
+
+ for (;;)
+ {
+ loopTimer(input_timeout_ms);
+#ifndef TW_OEM_BUILD
+ if (ors_read_fd > 0) {
+ FD_ZERO(&fdset);
+ FD_SET(ors_read_fd, &fdset);
+ timeout.tv_sec = 0;
+ timeout.tv_usec = 1;
+ has_data = select(ors_read_fd+1, &fdset, NULL, NULL, &timeout);
+ if (has_data > 0) {
+ ors_command_read();
+ }
+ }
+#endif
+
+ if (gGuiConsoleRunning.get_value()) {
+ continue;
+ }
+
+ if (!gForceRender.get_value())
+ {
+ int ret = PageManager::Update();
+ if (ret == 0)
+ ++idle_frames;
+ else
+ idle_frames = 0;
+ // due to possible animation objects, we need to delay activating the input timeout
+ input_timeout_ms = idle_frames > 15 ? 1000 : 0;
+
+#ifndef PRINT_RENDER_TIME
+ if (ret > 1)
+ PageManager::Render();
+
+ if (ret > 0)
+ flip();
+#else
+ if (ret > 1)
+ {
+ timespec start, end;
+ int32_t render_t, flip_t;
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ PageManager::Render();
+ clock_gettime(CLOCK_MONOTONIC, &end);
+ render_t = TWFunc::timespec_diff_ms(start, end);
+
+ flip();
+ clock_gettime(CLOCK_MONOTONIC, &start);
+ flip_t = TWFunc::timespec_diff_ms(end, start);
+
+ LOGINFO("Render(): %u ms, flip(): %u ms, total: %u ms\n", render_t, flip_t, render_t+flip_t);
+ }
+ else if (ret > 0)
+ flip();
+#endif
+ }
+ else
+ {
+ gForceRender.set_value(0);
+ PageManager::Render();
+ flip();
+ input_timeout_ms = 0;
+ }
+
+ blankTimer.checkForTimeout();
+ if (stop_on_page_done && DataManager::GetIntValue("tw_page_done") != 0)
+ {
+ gui_changePage("main");
+ break;
+ }
+ if (DataManager::GetIntValue("tw_gui_done") != 0)
+ break;
+ }
+ if (ors_read_fd > 0)
+ close(ors_read_fd);
+ ors_read_fd = -1;
+ gGuiRunning = 0;
+ return 0;
+}
+
+int gui_forceRender(void)
+{
+ gForceRender.set_value(1);
+ return 0;
+}
+
+int gui_changePage(std::string newPage)
+{
+ LOGINFO("Set page: '%s'\n", newPage.c_str());
+ PageManager::ChangePage(newPage);
+ gForceRender.set_value(1);
+ return 0;
+}
+
+int gui_changeOverlay(std::string overlay)
+{
+ LOGINFO("Set overlay: '%s'\n", overlay.c_str());
+ PageManager::ChangeOverlay(overlay);
+ gForceRender.set_value(1);
+ return 0;
+}
+
+int gui_changePackage(std::string newPackage)
+{
+ PageManager::SelectPackage(newPackage);
+ gForceRender.set_value(1);
+ return 0;
+}
+
+std::string gui_parse_text(std::string str)
+{
+ // This function parses text for DataManager values encompassed by %value% in the XML
+ // and string resources (%@resource_name%)
+ size_t pos = 0;
+
+ while (1)
+ {
+ size_t next = str.find('%', pos);
+ if (next == std::string::npos)
+ return str;
+
+ size_t end = str.find('%', next + 1);
+ if (end == std::string::npos)
+ return str;
+
+ // We have a block of data
+ std::string var = str.substr(next + 1, (end - next) - 1);
+ str.erase(next, (end - next) + 1);
+
+ if (next + 1 == end)
+ str.insert(next, 1, '%');
+ else
+ {
+ std::string value;
+ if (var.size() > 0 && var[0] == '@') {
+ // this is a string resource ("%@string_name%")
+ value = PageManager::GetResources()->FindString(var.substr(1));
+ str.insert(next, value);
+ }
+ else if (DataManager::GetValue(var, value) == 0)
+ str.insert(next, value);
+ }
+
+ pos = next + 1;
+ }
+}
+
+extern "C" int gui_init(void)
+{
+ gr_init();
+ std::string curtain_path = TWRES "images/curtain.jpg";
+ gr_surface source_Surface = NULL;
+
+ if (res_create_surface(curtain_path.c_str(), &source_Surface))
+ {
+ printf("Unable to locate '%s'\nDid you set a TW_THEME in your config files?\n", curtain_path.c_str());
+ return -1;
+ }
+ if (gr_get_width(source_Surface) != gr_fb_width() || gr_get_height(source_Surface) != gr_fb_height()) {
+ // We need to scale the curtain to fit the screen
+ float scale_w = (float)gr_fb_width() / (float)gr_get_width(source_Surface);
+ float scale_h = (float)gr_fb_height() / (float)gr_get_height(source_Surface);
+ if (res_scale_surface(source_Surface, &gCurtain, scale_w, scale_h)) {
+ LOGINFO("Failed to scale curtain\n");
+ gCurtain = source_Surface;
+ } else {
+ LOGINFO("Scaling the curtain width %fx and height %fx\n", scale_w, scale_h);
+ }
+ } else {
+ gCurtain = source_Surface;
+ }
+
+ curtainSet();
+
+ ev_init();
+ return 0;
+}
+
+extern "C" int gui_loadResources(void)
+{
+#ifndef TW_OEM_BUILD
+ int check = 0;
+ DataManager::GetValue(TW_IS_ENCRYPTED, check);
+
+ if (check)
+ {
+ if (PageManager::LoadPackage("TWRP", TWRES "ui.xml", "decrypt"))
+ {
+ LOGERR("Failed to load base packages.\n");
+ goto error;
+ }
+ else
+ check = 1;
+ }
+
+ if (check == 0 && PageManager::LoadPackage("TWRP", "/script/ui.xml", "main"))
+ {
+ std::string theme_path;
+
+ theme_path = DataManager::GetSettingsStoragePath();
+ if (!PartitionManager.Mount_Settings_Storage(false))
+ {
+ int retry_count = 5;
+ while (retry_count > 0 && !PartitionManager.Mount_Settings_Storage(false))
+ {
+ usleep(500000);
+ retry_count--;
+ }
+
+ if (!PartitionManager.Mount_Settings_Storage(false))
+ {
+ LOGERR("Unable to mount %s during GUI startup.\n",
+ theme_path.c_str());
+ check = 1;
+ }
+ }
+
+ theme_path += "/TWRP/theme/ui.zip";
+ if (check || PageManager::LoadPackage("TWRP", theme_path, "main"))
+ {
+#endif // ifndef TW_OEM_BUILD
+ if (PageManager::LoadPackage("TWRP", TWRES "ui.xml", "main"))
+ {
+ LOGERR("Failed to load base packages.\n");
+ goto error;
+ }
+#ifndef TW_OEM_BUILD
+ }
+ }
+#endif // ifndef TW_OEM_BUILD
+ // Set the default package
+ PageManager::SelectPackage("TWRP");
+
+ gGuiInitialized = 1;
+ return 0;
+
+error:
+ LOGERR("An internal error has occurred: unable to load theme.\n");
+ gGuiInitialized = 0;
+ return -1;
+}
+
+extern "C" int gui_loadCustomResources(void)
+{
+#ifndef TW_OEM_BUILD
+ if (!PartitionManager.Mount_Settings_Storage(false)) {
+ LOGERR("Unable to mount settings storage during GUI startup.\n");
+ return -1;
+ }
+
+ std::string theme_path = DataManager::GetSettingsStoragePath();
+ theme_path += "/TWRP/theme/ui.zip";
+ // Check for a custom theme
+ if (TWFunc::Path_Exists(theme_path)) {
+ // There is a custom theme, try to load it
+ if (PageManager::ReloadPackage("TWRP", theme_path)) {
+ // Custom theme failed to load, try to load stock theme
+ if (PageManager::ReloadPackage("TWRP", TWRES "ui.xml")) {
+ LOGERR("Failed to load base packages.\n");
+ goto error;
+ }
+ }
+ }
+ // Set the default package
+ PageManager::SelectPackage("TWRP");
+#endif
+ return 0;
+
+error:
+ LOGERR("An internal error has occurred: unable to load theme.\n");
+ gGuiInitialized = 0;
+ return -1;
+}
+
+extern "C" int gui_start(void)
+{
+ return gui_startPage(NULL, 1, 0);
+}
+
+extern "C" int gui_startPage(const char *page_name, const int allow_commands, int stop_on_page_done)
+{
+ if (!gGuiInitialized)
+ return -1;
+
+ gGuiConsoleTerminate.set_value(1);
+
+ while (gGuiConsoleRunning.get_value())
+ usleep(10000);
+
+ // Set the default package
+ PageManager::SelectPackage("TWRP");
+
+ input_handler.init();
+#ifndef TW_OEM_BUILD
+ if (allow_commands)
+ {
+ if (ors_read_fd < 0)
+ setup_ors_command();
+ } else {
+ if (ors_read_fd >= 0) {
+ close(ors_read_fd);
+ ors_read_fd = -1;
+ }
+ }
+#endif
+ return runPages(page_name, stop_on_page_done);
+}
+
+static void * console_thread(void *cookie)
+{
+ PageManager::SwitchToConsole();
+
+ while (!gGuiConsoleTerminate.get_value())
+ {
+ loopTimer(0);
+
+ if (!gForceRender.get_value())
+ {
+ int ret;
+
+ ret = PageManager::Update();
+ if (ret > 1)
+ PageManager::Render();
+
+ if (ret > 0)
+ flip();
+
+ if (ret < 0)
+ LOGERR("An update request has failed.\n");
+ }
+ else
+ {
+ gForceRender.set_value(0);
+ PageManager::Render();
+ flip();
+ }
+ }
+ gGuiConsoleRunning.set_value(0);
+ gForceRender.set_value(1); // this will kickstart the GUI to render again
+ PageManager::EndConsole();
+ LOGINFO("Console stopping\n");
+ return NULL;
+}
+
+extern "C" int gui_console_only(void)
+{
+ if (!gGuiInitialized)
+ return -1;
+
+ gGuiConsoleTerminate.set_value(0);
+
+ if (gGuiConsoleRunning.get_value())
+ return 0;
+
+ gGuiConsoleRunning.set_value(1);
+
+ // Start by spinning off an input handler.
+ pthread_t t;
+ pthread_create(&t, NULL, console_thread, NULL);
+
+ return 0;
+}
+
+extern "C" void set_scale_values(float w, float h)
+{
+ scale_theme_w = w;
+ scale_theme_h = h;
+}
+
+extern "C" int scale_theme_x(int initial_x)
+{
+ if (scale_theme_w != 1) {
+ int scaled = (float)initial_x * scale_theme_w;
+ if (scaled == 0 && initial_x > 0)
+ return 1;
+ return scaled;
+ }
+ return initial_x;
+}
+
+extern "C" int scale_theme_y(int initial_y)
+{
+ if (scale_theme_h != 1) {
+ int scaled = (float)initial_y * scale_theme_h;
+ if (scaled == 0 && initial_y > 0)
+ return 1;
+ return scaled;
+ }
+ return initial_y;
+}
+
+extern "C" int scale_theme_min(int initial_value)
+{
+ if (scale_theme_w != 1 || scale_theme_h != 1) {
+ if (scale_theme_w < scale_theme_h)
+ return scale_theme_x(initial_value);
+ else
+ return scale_theme_y(initial_value);
+ }
+ return initial_value;
+}
+
+extern "C" float get_scale_w()
+{
+ return scale_theme_w;
+}
+
+extern "C" float get_scale_h()
+{
+ return scale_theme_h;
+}
diff --git a/gui/gui.h b/gui/gui.h
new file mode 100644
index 000000000..f6f0483a4
--- /dev/null
+++ b/gui/gui.h
@@ -0,0 +1,42 @@
+/*
+ Copyright 2012 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#ifndef _GUI_HEADER
+#define _GUI_HEADER
+
+#include <stdio.h>
+
+int gui_console_only();
+int gui_init();
+int gui_loadResources();
+int gui_loadCustomResources();
+int gui_start();
+int gui_startPage(const char* page_name, const int allow_comands, int stop_on_page_done);
+void gui_print(const char *fmt, ...);
+void gui_print_color(const char *color, const char *fmt, ...);
+void gui_set_FILE(FILE* f);
+
+void set_scale_values(float w, float h);
+int scale_theme_x(int initial_x);
+int scale_theme_y(int initial_y);
+int scale_theme_min(int initial_value);
+float get_scale_w();
+float get_scale_h();
+
+#endif // _GUI_HEADER
+
diff --git a/gui/hardwarekeyboard.cpp b/gui/hardwarekeyboard.cpp
new file mode 100644
index 000000000..1f34c5e1d
--- /dev/null
+++ b/gui/hardwarekeyboard.cpp
@@ -0,0 +1,416 @@
+// hardwarekeyboard.cpp - HardwareKeyboard object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../common.h"
+}
+
+#include "objects.hpp"
+#include <linux/input.h>
+
+HardwareKeyboard::HardwareKeyboard()
+ : mLastKeyChar(0)
+{
+}
+
+HardwareKeyboard::~HardwareKeyboard()
+{
+}
+
+// Map keys to other keys.
+static int TranslateKeyCode(int key_code)
+{
+ switch (key_code) {
+ case KEY_HOMEPAGE: // Home key on Asus Transformer hardware keyboard
+ return KEY_HOME;
+ case KEY_SLEEP: // Lock key on Asus Transformer hardware keyboard
+ return KEY_POWER;
+ }
+ return key_code;
+}
+
+int HardwareKeyboard::KeyDown(int key_code)
+{
+#ifdef _EVENT_LOGGING
+ LOGE("HardwareKeyboard::KeyDown %i\n", key_code);
+#endif
+ key_code = TranslateKeyCode(key_code);
+
+ // determine if any Shift key is held down
+ bool shiftkey = false;
+ std::set<int>::iterator it = mPressedKeys.find(KEY_LEFTSHIFT);
+ if (it == mPressedKeys.end())
+ it = mPressedKeys.find(KEY_RIGHTSHIFT);
+ if (it != mPressedKeys.end())
+ shiftkey = true;
+
+ mPressedKeys.insert(key_code);
+
+ int keyboard = -1;
+
+ switch (key_code) {
+ case KEY_A:
+ if (shiftkey)
+ keyboard = 'A';
+ else
+ keyboard = 'a';
+ break;
+ case KEY_B:
+ if (shiftkey)
+ keyboard = 'B';
+ else
+ keyboard = 'b';
+ break;
+ case KEY_C:
+ if (shiftkey)
+ keyboard = 'C';
+ else
+ keyboard = 'c';
+ break;
+ case KEY_D:
+ if (shiftkey)
+ keyboard = 'D';
+ else
+ keyboard = 'd';
+ break;
+ case KEY_E:
+ if (shiftkey)
+ keyboard = 'E';
+ else
+ keyboard = 'e';
+ break;
+ case KEY_F:
+ if (shiftkey)
+ keyboard = 'F';
+ else
+ keyboard = 'f';
+ break;
+ case KEY_G:
+ if (shiftkey)
+ keyboard = 'G';
+ else
+ keyboard = 'g';
+ break;
+ case KEY_H:
+ if (shiftkey)
+ keyboard = 'H';
+ else
+ keyboard = 'h';
+ break;
+ case KEY_I:
+ if (shiftkey)
+ keyboard = 'I';
+ else
+ keyboard = 'i';
+ break;
+ case KEY_J:
+ if (shiftkey)
+ keyboard = 'J';
+ else
+ keyboard = 'j';
+ break;
+ case KEY_K:
+ if (shiftkey)
+ keyboard = 'K';
+ else
+ keyboard = 'k';
+ break;
+ case KEY_L:
+ if (shiftkey)
+ keyboard = 'L';
+ else
+ keyboard = 'l';
+ break;
+ case KEY_M:
+ if (shiftkey)
+ keyboard = 'M';
+ else
+ keyboard = 'm';
+ break;
+ case KEY_N:
+ if (shiftkey)
+ keyboard = 'N';
+ else
+ keyboard = 'n';
+ break;
+ case KEY_O:
+ if (shiftkey)
+ keyboard = 'O';
+ else
+ keyboard = 'o';
+ break;
+ case KEY_P:
+ if (shiftkey)
+ keyboard = 'P';
+ else
+ keyboard = 'p';
+ break;
+ case KEY_Q:
+ if (shiftkey)
+ keyboard = 'Q';
+ else
+ keyboard = 'q';
+ break;
+ case KEY_R:
+ if (shiftkey)
+ keyboard = 'R';
+ else
+ keyboard = 'r';
+ break;
+ case KEY_S:
+ if (shiftkey)
+ keyboard = 'S';
+ else
+ keyboard = 's';
+ break;
+ case KEY_T:
+ if (shiftkey)
+ keyboard = 'T';
+ else
+ keyboard = 't';
+ break;
+ case KEY_U:
+ if (shiftkey)
+ keyboard = 'U';
+ else
+ keyboard = 'u';
+ break;
+ case KEY_V:
+ if (shiftkey)
+ keyboard = 'V';
+ else
+ keyboard = 'v';
+ break;
+ case KEY_W:
+ if (shiftkey)
+ keyboard = 'W';
+ else
+ keyboard = 'w';
+ break;
+ case KEY_X:
+ if (shiftkey)
+ keyboard = 'X';
+ else
+ keyboard = 'x';
+ break;
+ case KEY_Y:
+ if (shiftkey)
+ keyboard = 'Y';
+ else
+ keyboard = 'y';
+ break;
+ case KEY_Z:
+ if (shiftkey)
+ keyboard = 'Z';
+ else
+ keyboard = 'z';
+ break;
+ case KEY_0:
+ if (shiftkey)
+ keyboard = ')';
+ else
+ keyboard = '0';
+ break;
+ case KEY_1:
+ if (shiftkey)
+ keyboard = '!';
+ else
+ keyboard = '1';
+ break;
+ case KEY_2:
+ if (shiftkey)
+ keyboard = '@';
+ else
+ keyboard = '2';
+ break;
+ case KEY_3:
+ if (shiftkey)
+ keyboard = '#';
+ else
+ keyboard = '3';
+ break;
+ case KEY_4:
+ if (shiftkey)
+ keyboard = '$';
+ else
+ keyboard = '4';
+ break;
+ case KEY_5:
+ if (shiftkey)
+ keyboard = '%';
+ else
+ keyboard = '5';
+ break;
+ case KEY_6:
+ if (shiftkey)
+ keyboard = '^';
+ else
+ keyboard = '6';
+ break;
+ case KEY_7:
+ if (shiftkey)
+ keyboard = '&';
+ else
+ keyboard = '7';
+ break;
+ case KEY_8:
+ if (shiftkey)
+ keyboard = '*';
+ else
+ keyboard = '8';
+ break;
+ case KEY_9:
+ if (shiftkey)
+ keyboard = '(';
+ else
+ keyboard = '9';
+ break;
+ case KEY_SPACE:
+ keyboard = ' ';
+ break;
+ case KEY_BACKSPACE:
+ keyboard = KEYBOARD_BACKSPACE;
+ break;
+ case KEY_ENTER:
+ keyboard = KEYBOARD_ACTION;
+ break;
+ case KEY_SLASH:
+ if (shiftkey)
+ keyboard = '?';
+ else
+ keyboard = '/';
+ break;
+ case KEY_DOT:
+ if (shiftkey)
+ keyboard = '>';
+ else
+ keyboard = '.';
+ break;
+ case KEY_COMMA:
+ if (shiftkey)
+ keyboard = '<';
+ else
+ keyboard = ',';
+ break;
+ case KEY_MINUS:
+ if (shiftkey)
+ keyboard = '_';
+ else
+ keyboard = '-';
+ break;
+ case KEY_GRAVE:
+ if (shiftkey)
+ keyboard = '~';
+ else
+ keyboard = '`';
+ break;
+ case KEY_EQUAL:
+ if (shiftkey)
+ keyboard = '+';
+ else
+ keyboard = '=';
+ break;
+ case KEY_LEFTBRACE:
+ if (shiftkey)
+ keyboard = '{';
+ else
+ keyboard = '[';
+ break;
+ case KEY_RIGHTBRACE:
+ if (shiftkey)
+ keyboard = '}';
+ else
+ keyboard = ']';
+ break;
+ case KEY_BACKSLASH:
+ if (shiftkey)
+ keyboard = '|';
+ else
+ keyboard = '\\';
+ break;
+ case KEY_SEMICOLON:
+ if (shiftkey)
+ keyboard = ':';
+ else
+ keyboard = ';';
+ break;
+ case KEY_APOSTROPHE:
+ if (shiftkey)
+ keyboard = '\"';
+ else
+ keyboard = '\'';
+ break;
+ case KEY_UP: // Up arrow
+ keyboard = KEYBOARD_ARROW_UP;
+ break;
+ case KEY_DOWN: // Down arrow
+ keyboard = KEYBOARD_ARROW_DOWN;
+ break;
+ case KEY_LEFT: // Left arrow
+ keyboard = KEYBOARD_ARROW_LEFT;
+ break;
+ case KEY_RIGHT: // Right arrow
+ keyboard = KEYBOARD_ARROW_RIGHT;
+ break;
+
+#ifdef _EVENT_LOGGING
+ default:
+ LOGE("Unmapped keycode: %i\n", key_code);
+ break;
+#endif
+ }
+ if (keyboard != -1) {
+ mLastKeyChar = keyboard;
+ // NotifyKeyboard means: "report character to input widget". KEYBOARD_* codes are special, others are ASCII chars.
+ if (!PageManager::NotifyKeyboard(keyboard))
+ return 1; // Return 1 to enable key repeat
+ } else {
+ mLastKeyChar = 0;
+ PageManager::NotifyKey(key_code, true);
+ }
+ return 0;
+}
+
+int HardwareKeyboard::KeyUp(int key_code)
+{
+#ifdef _EVENT_LOGGING
+ LOGE("HardwareKeyboard::KeyUp %i\n", key_code);
+#endif
+ key_code = TranslateKeyCode(key_code);
+ std::set<int>::iterator itr = mPressedKeys.find(key_code);
+ if (itr != mPressedKeys.end()) {
+ mPressedKeys.erase(itr);
+ PageManager::NotifyKey(key_code, false);
+ }
+ return 0;
+}
+
+int HardwareKeyboard::KeyRepeat()
+{
+#ifdef _EVENT_LOGGING
+ LOGE("HardwareKeyboard::KeyRepeat: %i\n", mLastKeyChar);
+#endif
+ if (mLastKeyChar)
+ PageManager::NotifyKeyboard(mLastKeyChar);
+ return 0;
+}
+
+void HardwareKeyboard::ConsumeKeyRelease(int key)
+{
+ // causes following KeyUp event to suppress notifications
+ mPressedKeys.erase(key);
+}
diff --git a/gui/image.cpp b/gui/image.cpp
new file mode 100644
index 000000000..8b43aaa34
--- /dev/null
+++ b/gui/image.cpp
@@ -0,0 +1,92 @@
+// image.cpp - GUIImage object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUIImage::GUIImage(xml_node<>* node) : GUIObject(node)
+{
+ mImage = NULL;
+ mHighlightImage = NULL;
+ isHighlighted = false;
+
+ if (!node)
+ return;
+
+ mImage = LoadAttrImage(FindNode(node, "image"), "resource");
+ mHighlightImage = LoadAttrImage(FindNode(node, "image"), "highlightresource");
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, NULL, NULL, &mPlacement);
+
+ if (mImage && mImage->GetResource())
+ {
+ mRenderW = mImage->GetWidth();
+ mRenderH = mImage->GetHeight();
+
+ // Adjust for placement
+ if (mPlacement != TOP_LEFT && mPlacement != BOTTOM_LEFT)
+ {
+ if (mPlacement == CENTER)
+ mRenderX -= (mRenderW / 2);
+ else
+ mRenderX -= mRenderW;
+ }
+ if (mPlacement != TOP_LEFT && mPlacement != TOP_RIGHT)
+ {
+ if (mPlacement == CENTER)
+ mRenderY -= (mRenderH / 2);
+ else
+ mRenderY -= mRenderH;
+ }
+ SetPlacement(TOP_LEFT);
+ }
+}
+
+int GUIImage::Render(void)
+{
+ if (!isConditionTrue())
+ return 0;
+
+ if (isHighlighted && mHighlightImage && mHighlightImage->GetResource()) {
+ gr_blit(mHighlightImage->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
+ return 0;
+ }
+ else if (!mImage || !mImage->GetResource())
+ return -1;
+
+ gr_blit(mImage->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
+ return 0;
+}
+
+int GUIImage::SetRenderPos(int x, int y, int w, int h)
+{
+ if (w || h)
+ return -1;
+
+ mRenderX = x;
+ mRenderY = y;
+ return 0;
+}
+
diff --git a/gui/input.cpp b/gui/input.cpp
new file mode 100644
index 000000000..ca27ea812
--- /dev/null
+++ b/gui/input.cpp
@@ -0,0 +1,713 @@
+/*
+ Copyright 2012 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// input.cpp - GUIInput object
+
+#include <linux/input.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../data.hpp"
+
+GUIInput::GUIInput(xml_node<>* node)
+ : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ mInputText = NULL;
+ mAction = NULL;
+ mBackground = NULL;
+ mCursor = NULL;
+ mFont = NULL;
+ mRendered = false;
+ HasMask = false;
+ DrawCursor = false;
+ isLocalChange = true;
+ HasAllowed = false;
+ HasDisabled = false;
+ skipChars = scrollingX = mFontHeight = mFontY = lastX = 0;
+ mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = MinLen = MaxLen = 0;
+ mCursorLocation = -1; // -1 is always the end of the string
+ CursorWidth = 3;
+ ConvertStrToColor("black", &mBackgroundColor);
+ ConvertStrToColor("white", &mCursorColor);
+
+ if (!node)
+ return;
+
+ // Load text directly from the node
+ mInputText = new GUIText(node);
+ // Load action directly from the node
+ mAction = new GUIAction(node);
+
+ if (mInputText->Render() < 0)
+ {
+ delete mInputText;
+ mInputText = NULL;
+ }
+
+ // Load the background
+ child = FindNode(node, "background");
+ if (child)
+ {
+ mBackground = LoadAttrImage(child, "resource");
+ mBackgroundColor = LoadAttrColor(child, "color", mBackgroundColor);
+ }
+ if (mBackground && mBackground->GetResource())
+ {
+ mBackgroundW = mBackground->GetWidth();
+ mBackgroundH = mBackground->GetHeight();
+ }
+
+ // Load the cursor color
+ child = FindNode(node, "cursor");
+ if (child)
+ {
+ mCursor = LoadAttrImage(child, "resource");
+ mCursorColor = LoadAttrColor(child, "color", mCursorColor);
+ attr = child->first_attribute("hasfocus");
+ if (attr)
+ {
+ std::string focus = attr->value();
+ SetInputFocus(atoi(focus.c_str()));
+ }
+ CursorWidth = LoadAttrIntScaleX(child, "width", CursorWidth);
+ }
+ DrawCursor = HasInputFocus;
+
+ // Load the font
+ child = FindNode(node, "font");
+ if (child)
+ {
+ mFont = LoadAttrFont(child, "resource");
+ mFontHeight = mFont->GetHeight();
+ }
+
+ child = FindNode(node, "text");
+ if (child) mText = child->value();
+ mLastValue = gui_parse_text(mText);
+
+ child = FindNode(node, "data");
+ if (child)
+ {
+ attr = child->first_attribute("name");
+ if (attr)
+ mVariable = attr->value();
+ attr = child->first_attribute("default");
+ if (attr)
+ DataManager::SetValue(mVariable, attr->value());
+ mMask = LoadAttrString(child, "mask");
+ HasMask = !mMask.empty();
+ attr = child->first_attribute("maskvariable");
+ if (attr)
+ mMaskVariable = attr->value();
+ else
+ mMaskVariable = mVariable;
+ }
+
+ // Load input restrictions
+ child = FindNode(node, "restrict");
+ if (child)
+ {
+ MinLen = LoadAttrInt(child, "minlen", MinLen);
+ MaxLen = LoadAttrInt(child, "maxlen", MaxLen);
+ AllowedList = LoadAttrString(child, "allow");
+ HasAllowed = !AllowedList.empty();
+ DisabledList = LoadAttrString(child, "disable");
+ HasDisabled = !DisabledList.empty();
+ }
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
+ SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+
+ if (mInputText && mFontHeight && mFontHeight < (unsigned)mRenderH) {
+ mFontY = ((mRenderH - mFontHeight) / 2) + mRenderY;
+ mInputText->SetRenderPos(mRenderX, mFontY);
+ } else
+ mFontY = mRenderY;
+
+ if (mInputText)
+ mInputText->SetMaxWidth(mRenderW);
+
+ isLocalChange = false;
+ HandleTextLocation(-3);
+}
+
+GUIInput::~GUIInput()
+{
+ delete mInputText;
+ delete mAction;
+}
+
+int GUIInput::HandleTextLocation(int x)
+{
+ int textWidth;
+ string displayValue, originalValue, insertChar;
+ void* fontResource = NULL;
+
+ if (mFont)
+ fontResource = mFont->GetResource();
+
+ DataManager::GetValue(mVariable, originalValue);
+ displayValue = originalValue;
+ if (HasMask) {
+ int index, string_size = displayValue.size();
+ string maskedValue;
+ for (index=0; index<string_size; index++)
+ maskedValue += mMask;
+ displayValue = maskedValue;
+ }
+ textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+ if (textWidth <= mRenderW) {
+ lastX = x;
+ scrollingX = 0;
+ skipChars = 0;
+ mInputText->SkipCharCount(skipChars);
+ mRendered = false;
+ return 0;
+ }
+
+ if (skipChars && skipChars < displayValue.size())
+ displayValue.erase(0, skipChars);
+
+ textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+ mRendered = false;
+
+ int deltaX, deltaText, newWidth;
+
+ if (x < -1000) {
+ // No change in scrolling
+ if (x == -1003)
+ mCursorLocation = -1;
+
+ if (mCursorLocation == -1) {
+ displayValue = originalValue;
+ skipChars = 0;
+ textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+ while (textWidth > mRenderW) {
+ displayValue.erase(0, 1);
+ skipChars++;
+ textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+ }
+ scrollingX = mRenderW - textWidth;
+ mInputText->SkipCharCount(skipChars);
+ } else if (x == -1001) {
+ // Added a new character
+ int adjust_scrollingX = 0;
+ string cursorLocate;
+
+ cursorLocate = displayValue;
+ cursorLocate.resize(mCursorLocation);
+ textWidth = gr_measureEx(cursorLocate.c_str(), fontResource);
+ while (textWidth > mRenderW) {
+ skipChars++;
+ mCursorLocation--;
+ cursorLocate.erase(0, 1);
+ textWidth = gr_measureEx(cursorLocate.c_str(), fontResource);
+ adjust_scrollingX = -1;
+ }
+ if (adjust_scrollingX) {
+ scrollingX = mRenderW - textWidth;
+ if (scrollingX < 0)
+ scrollingX = 0;
+ }
+ mInputText->SkipCharCount(skipChars);
+ } else if (x == -1002) {
+ // Deleted a character
+ while (-1) {
+ if (skipChars == 0) {
+ scrollingX = 0;
+ mInputText->SkipCharCount(skipChars);
+ return 0;
+ }
+ insertChar = originalValue.substr(skipChars - 1, 1);
+ displayValue.insert(0, insertChar);
+ newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+ deltaText = newWidth - textWidth;
+ if (newWidth > mRenderW) {
+ scrollingX = mRenderW - textWidth;
+ if (scrollingX < 0)
+ scrollingX = 0;
+ mInputText->SkipCharCount(skipChars);
+ return 0;
+ } else {
+ textWidth = newWidth;
+ skipChars--;
+ mCursorLocation++;
+ }
+ }
+ } else
+ LOGINFO("GUIInput::HandleTextLocation -> We really shouldn't ever get here...\n");
+ } else if (x > lastX) {
+ // Dragging to right, scrolling left
+ while (-1) {
+ deltaX = x - lastX + scrollingX;
+ if (skipChars == 0 || deltaX == 0) {
+ scrollingX = 0;
+ lastX = x;
+ mInputText->SkipCharCount(skipChars);
+ return 0;
+ }
+ insertChar = originalValue.substr(skipChars - 1, 1);
+ displayValue.insert(0, insertChar);
+ newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+ deltaText = newWidth - textWidth;
+ if (deltaText < deltaX) {
+ lastX += deltaText;
+ textWidth = newWidth;
+ skipChars--;
+ } else {
+ scrollingX = deltaX;
+ lastX = x;
+ mInputText->SkipCharCount(skipChars);
+ return 0;
+ }
+ }
+ } else if (x < lastX) {
+ // Dragging to left, scrolling right
+ if (textWidth <= mRenderW) {
+ lastX = x;
+ scrollingX = mRenderW - textWidth;
+ return 0;
+ }
+ if (scrollingX) {
+ deltaX = lastX - x;
+ if (scrollingX > deltaX) {
+ scrollingX -= deltaX;
+ lastX = x;
+ return 0;
+ } else {
+ lastX -= deltaX;
+ scrollingX = 0;
+ }
+ }
+ while (-1) {
+ deltaX = lastX - x;
+ displayValue.erase(0, 1);
+ skipChars++;
+ newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+ deltaText = textWidth - newWidth;
+ if (newWidth <= mRenderW) {
+ scrollingX = mRenderW - newWidth;
+ lastX = x;
+ mInputText->SkipCharCount(skipChars);
+ return 0;
+ }
+ if (deltaText < deltaX) {
+ lastX -= deltaText;
+ textWidth = newWidth;
+ } else {
+ scrollingX = deltaText - deltaX;
+ lastX = x;
+ mInputText->SkipCharCount(skipChars);
+ return 0;
+ }
+ }
+ }
+ return 0;
+}
+
+int GUIInput::Render(void)
+{
+ if (!isConditionTrue())
+ {
+ mRendered = false;
+ return 0;
+ }
+
+ void* fontResource = NULL;
+ if (mFont) fontResource = mFont->GetResource();
+
+ // First step, fill background
+ gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
+ gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
+
+ // Next, render the background resource (if it exists)
+ if (mBackground && mBackground->GetResource())
+ {
+ mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
+ mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
+ gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
+ }
+
+ int ret = 0;
+
+ // Render the text
+ mInputText->SetRenderPos(mRenderX + scrollingX, mFontY);
+ mInputText->SetMaxWidth(mRenderW - scrollingX);
+ if (mInputText) ret = mInputText->Render();
+ if (ret < 0) return ret;
+
+ if (HasInputFocus && DrawCursor) {
+ // Render the cursor
+ string displayValue;
+ int cursorX;
+ DataManager::GetValue(mVariable, displayValue);
+ if (HasMask) {
+ int index, string_size = displayValue.size();
+ string maskedValue;
+ for (index=0; index<string_size; index++)
+ maskedValue += mMask;
+ displayValue = maskedValue;
+ }
+ if (displayValue.size() == 0) {
+ skipChars = 0;
+ mCursorLocation = -1;
+ cursorX = mRenderX;
+ } else {
+ if (skipChars && skipChars < displayValue.size()) {
+ displayValue.erase(0, skipChars);
+ }
+ if (mCursorLocation == 0) {
+ // Cursor is at the beginning
+ cursorX = mRenderX;
+ } else if (mCursorLocation > 0) {
+ // Cursor is in the middle
+ if (displayValue.size() > (unsigned)mCursorLocation) {
+ string cursorDisplay;
+
+ cursorDisplay = displayValue;
+ cursorDisplay.resize(mCursorLocation);
+ cursorX = gr_measureEx(cursorDisplay.c_str(), fontResource) + mRenderX;
+ } else {
+ // Cursor location is after the end of the text - reset to -1
+ mCursorLocation = -1;
+ cursorX = gr_measureEx(displayValue.c_str(), fontResource) + mRenderX;
+ }
+ } else {
+ // Cursor is at the end (-1)
+ cursorX = gr_measureEx(displayValue.c_str(), fontResource) + mRenderX;
+ }
+ }
+ cursorX += scrollingX;
+ // Make sure that the cursor doesn't go past the boundaries of the box
+ if (cursorX + (int)CursorWidth > mRenderX + mRenderW)
+ cursorX = mRenderX + mRenderW - CursorWidth;
+
+ // Set the color for the cursor
+ gr_color(mCursorColor.red, mCursorColor.green, mCursorColor.blue, 255);
+ gr_fill(cursorX, mFontY, CursorWidth, mFontHeight);
+ }
+
+ mRendered = true;
+ return ret;
+}
+
+int GUIInput::Update(void)
+{
+ if (!isConditionTrue()) return (mRendered ? 2 : 0);
+ if (!mRendered) return 2;
+
+ int ret = 0;
+
+ if (mInputText) ret = mInputText->Update();
+ if (ret < 0) return ret;
+
+ return ret;
+}
+
+int GUIInput::GetSelection(int x, int y)
+{
+ if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH) return -1;
+ return (x - mRenderX);
+}
+
+int GUIInput::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ static int startSelection = -1;
+ int textWidth;
+ string displayValue, originalValue;
+ void* fontResource = NULL;
+
+ if (mFont) fontResource = mFont->GetResource();
+
+ if (!isConditionTrue())
+ return -1;
+
+ if (!HasInputFocus) {
+ if (state != TOUCH_RELEASE)
+ return 0; // Only change focus if touch releases within the input box
+ if (GetSelection(x, y) >= 0) {
+ // When changing focus, we don't scroll or change the cursor location
+ PageManager::SetKeyBoardFocus(0);
+ PageManager::NotifyKeyboard(0);
+ SetInputFocus(1);
+ DrawCursor = true;
+ mRendered = false;
+ }
+ } else {
+ switch (state) {
+ case TOUCH_HOLD:
+ case TOUCH_REPEAT:
+ break;
+ case TOUCH_START:
+ startSelection = GetSelection(x,y);
+ lastX = x;
+ DrawCursor = false;
+ mRendered = false;
+ break;
+
+ case TOUCH_DRAG:
+ // Check if we dragged out of the selection window
+ if (GetSelection(x, y) == -1) {
+ lastX = 0;
+ break;
+ }
+
+ DrawCursor = false;
+
+ // Provide some debounce on initial touches
+ if (startSelection != -1 && abs(x - lastX) < 6) {
+ break;
+ }
+
+ startSelection = -1;
+ if (lastX != x)
+ HandleTextLocation(x);
+ break;
+
+ case TOUCH_RELEASE:
+ // We've moved the cursor location
+ int relativeX = x - mRenderX;
+
+ mRendered = false;
+ DrawCursor = true;
+ DataManager::GetValue(mVariable, displayValue);
+ if (HasMask) {
+ int index, string_size = displayValue.size();
+ string maskedValue;
+ for (index=0; index<string_size; index++)
+ maskedValue += mMask;
+ displayValue = maskedValue;
+ }
+ if (displayValue.size() == 0) {
+ skipChars = 0;
+ mCursorLocation = -1;
+ return 0;
+ } else if (skipChars && skipChars < displayValue.size()) {
+ displayValue.erase(0, skipChars);
+ }
+
+ string cursorString;
+ int cursorX = 0;
+ unsigned index = 0;
+
+ for(index=0; index<displayValue.size(); index++)
+ {
+ cursorString = displayValue.substr(0, index);
+ cursorX = gr_measureEx(cursorString.c_str(), fontResource) + mRenderX;
+ if (cursorX > x) {
+ if (index > 0)
+ mCursorLocation = index - 1;
+ else
+ mCursorLocation = index;
+ return 0;
+ }
+ }
+ mCursorLocation = -1;
+ break;
+ }
+ }
+ return 0;
+}
+
+int GUIInput::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIObject::NotifyVarChange(varName, value);
+
+ if (varName == mVariable && !isLocalChange) {
+ HandleTextLocation(-1003);
+ return 0;
+ }
+ return 0;
+}
+
+int GUIInput::NotifyKeyboard(int key)
+{
+ string variableValue;
+
+ if (HasInputFocus) {
+ if (key == KEYBOARD_BACKSPACE) {
+ //Backspace
+ DataManager::GetValue(mVariable, variableValue);
+ if (variableValue.size() > 0 && (mCursorLocation + skipChars != 0 || mCursorLocation == -1)) {
+ if (mCursorLocation == -1) {
+ variableValue.resize(variableValue.size() - 1);
+ } else {
+ variableValue.erase(mCursorLocation + skipChars - 1, 1);
+ if (mCursorLocation > 0)
+ mCursorLocation--;
+ else if (skipChars > 0)
+ skipChars--;
+ }
+ isLocalChange = true;
+ DataManager::SetValue(mVariable, variableValue);
+ isLocalChange = false;
+
+ if (HasMask) {
+ int index, string_size = variableValue.size();
+ string maskedValue;
+ for (index=0; index<string_size; index++)
+ maskedValue += mMask;
+ DataManager::SetValue(mMaskVariable, maskedValue);
+ }
+ HandleTextLocation(-1002);
+ }
+ } else if (key == KEYBOARD_SWIPE_LEFT) {
+ // Delete all
+ isLocalChange = true;
+ if (mCursorLocation == -1) {
+ DataManager::SetValue (mVariable, "");
+ if (HasMask)
+ DataManager::SetValue(mMaskVariable, "");
+ mCursorLocation = -1;
+ } else {
+ DataManager::GetValue(mVariable, variableValue);
+ variableValue.erase(0, mCursorLocation + skipChars);
+ DataManager::SetValue(mVariable, variableValue);
+ if (HasMask) {
+ DataManager::GetValue(mMaskVariable, variableValue);
+ variableValue.erase(0, mCursorLocation + skipChars);
+ DataManager::SetValue(mMaskVariable, variableValue);
+ }
+ mCursorLocation = 0;
+ }
+ skipChars = 0;
+ scrollingX = 0;
+ mInputText->SkipCharCount(skipChars);
+ isLocalChange = false;
+ mRendered = false;
+ return 0;
+ } else if (key == KEYBOARD_ARROW_LEFT) {
+ if (mCursorLocation == 0 && skipChars == 0)
+ return 0; // we're already at the beginning
+ if (mCursorLocation == -1) {
+ DataManager::GetValue(mVariable, variableValue);
+ if (variableValue.size() == 0)
+ return 0;
+ mCursorLocation = variableValue.size() - skipChars - 1;
+ } else if (mCursorLocation == 0) {
+ skipChars--;
+ HandleTextLocation(-1002);
+ } else {
+ mCursorLocation--;
+ HandleTextLocation(-1002);
+ }
+ mRendered = false;
+ return 0;
+ } else if (key == KEYBOARD_ARROW_RIGHT) {
+ if (mCursorLocation == -1)
+ return 0; // we're already at the end
+ mCursorLocation++;
+ DataManager::GetValue(mVariable, variableValue);
+ if (variableValue.size() <= mCursorLocation + skipChars)
+ mCursorLocation = -1;
+ HandleTextLocation(-1001);
+ mRendered = false;
+ return 0;
+ } else if (key == KEYBOARD_HOME || key == KEYBOARD_ARROW_UP) {
+ DataManager::GetValue(mVariable, variableValue);
+ if (variableValue.size() == 0)
+ return 0;
+ mCursorLocation = 0;
+ skipChars = 0;
+ mRendered = false;
+ HandleTextLocation(-1002);
+ return 0;
+ } else if (key == KEYBOARD_END || key == KEYBOARD_ARROW_DOWN) {
+ mCursorLocation = -1;
+ mRendered = false;
+ HandleTextLocation(-1003);
+ return 0;
+ } else if (key < KEYBOARD_SPECIAL_KEYS && key > 0) {
+ // Regular key
+ if (HasAllowed && AllowedList.find((char)key) == string::npos) {
+ return 0;
+ }
+ if (HasDisabled && DisabledList.find((char)key) != string::npos) {
+ return 0;
+ }
+ DataManager::GetValue(mVariable, variableValue);
+ if (MaxLen != 0 && variableValue.size() >= MaxLen) {
+ return 0;
+ }
+ if (mCursorLocation == -1) {
+ variableValue += key;
+ } else {
+ variableValue.insert(mCursorLocation + skipChars, 1, key);
+ mCursorLocation++;
+ }
+ isLocalChange = true;
+ DataManager::SetValue(mVariable, variableValue);
+ HandleTextLocation(-1001);
+ isLocalChange = false;
+
+ if (HasMask) {
+ int index, string_size = variableValue.size();
+ string maskedValue;
+ for (index=0; index<string_size; index++)
+ maskedValue += mMask;
+ DataManager::SetValue(mMaskVariable, maskedValue);
+ }
+ } else if (key == KEYBOARD_ACTION) {
+ // Action
+ DataManager::GetValue(mVariable, variableValue);
+ if (mAction) {
+ unsigned inputLen = variableValue.length();
+ if (inputLen < MinLen)
+ return 0;
+ else if (MaxLen != 0 && inputLen > MaxLen)
+ return 0;
+ else
+ return (mAction ? mAction->NotifyTouch(TOUCH_RELEASE, mRenderX, mRenderY) : 1);
+ }
+ }
+ return 0;
+ } else {
+ if (key == 0) {
+ // Somewhat ugly hack-ish way to tell the box to redraw after losing focus to remove the cursor
+ mRendered = false;
+ return 1;
+ }
+ }
+ return 1;
+}
diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp
new file mode 100644
index 000000000..f35a5d318
--- /dev/null
+++ b/gui/keyboard.cpp
@@ -0,0 +1,571 @@
+/*
+ Copyright 2012 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "../data.hpp"
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+#include "gui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUIKeyboard::GUIKeyboard(xml_node<>* node)
+ : GUIObject(node)
+{
+ int layoutindex, rowindex, keyindex, Xindex, Yindex, keyHeight = 0, keyWidth = 0;
+ currentKey = NULL;
+ highlightRenderCount = 0;
+ hasHighlight = hasCapsHighlight = false;
+ char resource[10], layout[8], row[5], key[6], longpress[7];
+ xml_attribute<>* attr;
+ xml_node<>* child;
+ xml_node<>* keylayout;
+ xml_node<>* keyrow;
+
+ for (layoutindex=0; layoutindex<MAX_KEYBOARD_LAYOUTS; layoutindex++) {
+ layouts[layoutindex].keyboardImg = NULL;
+ memset(layouts[layoutindex].keys, 0, sizeof(Layout::keys));
+ memset(layouts[layoutindex].row_end_y, 0, sizeof(Layout::row_end_y));
+ }
+
+ mRendered = false;
+ currentLayout = 1;
+ CapsLockOn = false;
+
+ if (!node) return;
+
+ mHighlightColor = LoadAttrColor(FindNode(node, "highlight"), "color", &hasHighlight);
+ mCapsHighlightColor = LoadAttrColor(FindNode(node, "capshighlight"), "color", &hasCapsHighlight);
+
+ child = FindNode(node, "keymargin");
+ mKeyMarginX = LoadAttrIntScaleX(child, "x", 0);
+ mKeyMarginY = LoadAttrIntScaleY(child, "y", 0);
+
+ child = FindNode(node, "background");
+ mBackgroundColor = LoadAttrColor(child, "color", COLOR(32,32,32,255));
+
+ child = FindNode(node, "key-alphanumeric");
+ mFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel"));
+ mFontColor = LoadAttrColor(child, "textcolor", COLOR(255,255,255,255));
+ mKeyColorAlphanumeric = LoadAttrColor(child, "color", COLOR(0,0,0,0));
+
+ child = FindNode(node, "key-other");
+ mSmallFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel-small"));
+ mFontColorSmall = LoadAttrColor(child, "textcolor", COLOR(192,192,192,255));
+ mKeyColorOther = LoadAttrColor(child, "color", COLOR(0,0,0,0));
+
+ child = FindNode(node, "longpress");
+ mLongpressFont = PageManager::GetResources()->FindFont(LoadAttrString(child, "font", "keylabel-longpress"));
+ mLongpressFontColor = LoadAttrColor(child, "textcolor", COLOR(128,128,128,255));
+ LoadPlacement(child, &longpressOffsetX, &longpressOffsetY);
+
+ LoadKeyLabels(node, 0); // load global key labels
+
+ // compatibility ugliness: resources should be specified in the layouts themselves instead
+ // Load the images for the different layouts
+ child = FindNode(node, "layout");
+ if (child)
+ {
+ layoutindex = 1;
+ strcpy(resource, "resource1");
+ attr = child->first_attribute(resource);
+ while (attr && layoutindex < (MAX_KEYBOARD_LAYOUTS + 1)) {
+ layouts[layoutindex - 1].keyboardImg = LoadAttrImage(child, resource);
+
+ layoutindex++;
+ resource[8] = (char)(layoutindex + 48);
+ attr = child->first_attribute(resource);
+ }
+ }
+
+ // Check the first image to get height and width
+ if (layouts[0].keyboardImg && layouts[0].keyboardImg->GetResource())
+ {
+ mRenderW = layouts[0].keyboardImg->GetWidth();
+ mRenderH = layouts[0].keyboardImg->GetHeight();
+ }
+
+ // Load all of the layout maps
+ layoutindex = 1;
+ strcpy(layout, "layout1");
+ keylayout = FindNode(node, layout);
+ while (keylayout)
+ {
+ if (layoutindex > MAX_KEYBOARD_LAYOUTS) {
+ LOGERR("Too many layouts defined in keyboard.\n");
+ return;
+ }
+
+ LoadKeyLabels(keylayout, layoutindex); // load per-layout key labels
+
+ Layout& lay = layouts[layoutindex - 1];
+
+ child = keylayout->first_node("keysize");
+ keyHeight = LoadAttrIntScaleY(child, "height", 0);
+ keyWidth = LoadAttrIntScaleX(child, "width", 0);
+ // compatibility ugliness: capslock="0" means that this is the caps layout. Also it has nothing to do with keysize.
+ lay.is_caps = (LoadAttrInt(child, "capslock", 1) == 0);
+ // compatibility ugliness: revert_layout has nothing to do with keysize.
+ lay.revert_layout = LoadAttrInt(child, "revert_layout", -1);
+
+ rowindex = 1;
+ Yindex = 0;
+ strcpy(row, "row1");
+ keyrow = keylayout->first_node(row);
+ while (keyrow)
+ {
+ if (rowindex > MAX_KEYBOARD_ROWS) {
+ LOGERR("Too many rows defined in keyboard.\n");
+ return;
+ }
+
+ Yindex += keyHeight;
+ lay.row_end_y[rowindex - 1] = Yindex;
+
+ keyindex = 1;
+ Xindex = 0;
+ strcpy(key, "key01");
+ attr = keyrow->first_attribute(key);
+
+ while (attr) {
+ if (keyindex > MAX_KEYBOARD_KEYS) {
+ LOGERR("Too many keys defined in a keyboard row.\n");
+ return;
+ }
+
+ const char* keyinfo = attr->value();
+
+ if (strlen(keyinfo) == 0) {
+ LOGERR("No key info on layout%i, row%i, key%dd.\n", layoutindex, rowindex, keyindex);
+ return;
+ }
+
+ if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, false))
+ LOGERR("Invalid key info on layout%i, row%i, key%02i.\n", layoutindex, rowindex, keyindex);
+
+
+ // PROCESS LONG PRESS INFO IF EXISTS
+ sprintf(longpress, "long%02i", keyindex);
+ attr = keyrow->first_attribute(longpress);
+ if (attr) {
+ const char* keyinfo = attr->value();
+
+ if (strlen(keyinfo) == 0) {
+ LOGERR("No long press info on layout%i, row%i, long%dd.\n", layoutindex, rowindex, keyindex);
+ return;
+ }
+
+ if (ParseKey(keyinfo, lay.keys[rowindex - 1][keyindex - 1], Xindex, keyWidth, true))
+ LOGERR("Invalid long press key info on layout%i, row%i, long%02i.\n", layoutindex, rowindex, keyindex);
+ }
+ keyindex++;
+ sprintf(key, "key%02i", keyindex);
+ attr = keyrow->first_attribute(key);
+ }
+ rowindex++;
+ row[3] = (char)(rowindex + 48);
+ keyrow = keylayout->first_node(row);
+ }
+ layoutindex++;
+ layout[6] = (char)(layoutindex + 48);
+ keylayout = FindNode(node, layout);
+ }
+
+ int x, y;
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &x, &y, &mRenderW, &mRenderH);
+ SetRenderPos(x, y, mRenderW, mRenderH);
+ return;
+}
+
+GUIKeyboard::~GUIKeyboard()
+{
+}
+
+int GUIKeyboard::ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWidth, bool longpress)
+{
+ key.layout = 0;
+ int keychar = 0;
+ if (strlen(keyinfo) == 1) {
+ // This is a single key, simple definition
+ keychar = keyinfo[0];
+ } else {
+ // This key has extra data: {keywidth}:{what_the_key_does}
+ keyWidth = scale_theme_x(atoi(keyinfo));
+
+ const char* ptr = keyinfo;
+ while (*ptr > 32 && *ptr != ':')
+ ptr++;
+ if (*ptr != ':')
+ return -1; // no colon is an error
+ ptr++;
+
+ if (*ptr == 0) { // This is an empty area
+ keychar = 0;
+ } else if (strlen(ptr) == 1) { // This is the character that this key uses
+ keychar = *ptr;
+ } else if (*ptr == 'c') { // This is an ASCII character code: "c:{number}"
+ keychar = atoi(ptr + 2);
+ } else if (*ptr == 'l') { // This is a different layout: "layout{number}"
+ keychar = KEYBOARD_LAYOUT;
+ key.layout = atoi(ptr + 6);
+ } else if (*ptr == 'a') { // This is an action: "action"
+ keychar = KEYBOARD_ACTION;
+ } else
+ return -1;
+ }
+
+ if (longpress) {
+ key.longpresskey = keychar;
+ } else {
+ key.key = keychar;
+ Xindex += keyWidth;
+ key.end_x = Xindex - 1;
+ }
+
+ return 0;
+}
+
+void GUIKeyboard::LoadKeyLabels(xml_node<>* parent, int layout)
+{
+ for (xml_node<>* child = parent->first_node(); child; child = child->next_sibling()) {
+ std::string name = child->name();
+ if (name == "keylabel") {
+ std::string keydef = LoadAttrString(child, "key", "");
+ Key tempkey;
+ int dummyX;
+ if (ParseKey(keydef.c_str(), tempkey, dummyX, 0, false) == 0) {
+ KeyLabel keylabel;
+ keylabel.key = tempkey.key;
+ keylabel.layout_from = layout;
+ keylabel.layout_to = tempkey.layout;
+ keylabel.text = LoadAttrString(child, "text", "");
+ keylabel.image = LoadAttrImage(child, "resource");
+ mKeyLabels.push_back(keylabel);
+ } else {
+ LOGERR("Ignoring invalid keylabel in layout %d: '%s'.\n", layout, keydef.c_str());
+ }
+ }
+ }
+}
+
+void GUIKeyboard::DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH)
+{
+ unsigned char keychar = key.key;
+ if (!keychar)
+ return;
+
+ // key background
+ COLOR& c = (keychar >= 32 && keychar < 127) ? mKeyColorAlphanumeric : mKeyColorOther;
+ gr_color(c.red, c.green, c.blue, c.alpha);
+ keyX += mKeyMarginX;
+ keyY += mKeyMarginY;
+ keyW -= mKeyMarginX * 2;
+ keyH -= mKeyMarginY * 2;
+ gr_fill(keyX, keyY, keyW, keyH);
+
+ // key label
+ FontResource* labelFont = mFont;
+ string labelText;
+ ImageResource* labelImage = NULL;
+ if (keychar > 32 && keychar < 127) {
+ labelText = (char) keychar;
+ gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
+ }
+ else {
+ // search for a special key label
+ for (std::vector<KeyLabel>::iterator it = mKeyLabels.begin(); it != mKeyLabels.end(); ++it) {
+ if (it->layout_from > 0 && it->layout_from != currentLayout)
+ continue; // this label is for another layout
+ if (it->key == key.key && it->layout_to == key.layout)
+ {
+ // found a label
+ labelText = it->text;
+ labelImage = it->image;
+ break;
+ }
+ }
+ labelFont = mSmallFont;
+ gr_color(mFontColorSmall.red, mFontColorSmall.green, mFontColorSmall.blue, mFontColorSmall.alpha);
+ }
+
+ if (labelImage)
+ {
+ int w = labelImage->GetWidth();
+ int h = labelImage->GetHeight();
+ int x = keyX + (keyW - w) / 2;
+ int y = keyY + (keyH - h) / 2;
+ gr_blit(labelImage->GetResource(), 0, 0, w, h, x, y);
+ }
+ else if (!labelText.empty())
+ {
+ void* fontResource = labelFont->GetResource();
+ int textW = gr_measureEx(labelText.c_str(), fontResource);
+ int textH = labelFont->GetHeight();
+ int textX = keyX + (keyW - textW) / 2;
+ int textY = keyY + (keyH - textH) / 2;
+ gr_textEx(textX, textY, labelText.c_str(), fontResource);
+ }
+
+ // longpress key label (only if font is defined)
+ keychar = key.longpresskey;
+ if (keychar > 32 && keychar < 127 && mLongpressFont->GetResource()) {
+ void* fontResource = mLongpressFont->GetResource();
+ gr_color(mLongpressFontColor.red, mLongpressFontColor.green, mLongpressFontColor.blue, mLongpressFontColor.alpha);
+ string text(1, keychar);
+ int textH = mLongpressFont->GetHeight();
+ int textW = gr_measureEx(text.c_str(), fontResource);
+ int textX = keyX + keyW - longpressOffsetX - textW;
+ int textY = keyY + longpressOffsetY;
+ gr_textEx(textX, textY, text.c_str(), fontResource);
+ }
+}
+
+int GUIKeyboard::Render(void)
+{
+ if (!isConditionTrue())
+ {
+ mRendered = false;
+ return 0;
+ }
+
+ Layout& lay = layouts[currentLayout - 1];
+
+ bool drawKeys = false;
+ if (lay.keyboardImg && lay.keyboardImg->GetResource())
+ // keyboard is image based
+ gr_blit(lay.keyboardImg->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
+ else {
+ // keyboard is software drawn
+ // fill background
+ gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha);
+ gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
+ drawKeys = true;
+ }
+
+ // draw keys
+ int y1 = 0;
+ for (int row = 0; row < MAX_KEYBOARD_ROWS; ++row) {
+ int rowY = mRenderY + y1;
+ int rowH = lay.row_end_y[row] - y1;
+ y1 = lay.row_end_y[row];
+ int x1 = 0;
+ for (int col = 0; col < MAX_KEYBOARD_KEYS; ++col) {
+ Key& key = lay.keys[row][col];
+ int keyY = rowY;
+ int keyH = rowH;
+ int keyX = mRenderX + x1;
+ int keyW = key.end_x - x1;
+ x1 = key.end_x;
+
+ // Draw key for software drawn keyboard
+ if (drawKeys)
+ DrawKey(key, keyX, keyY, keyW, keyH);
+
+ // Draw highlight for capslock
+ if (hasCapsHighlight && lay.is_caps && CapsLockOn && (int)key.key == KEYBOARD_LAYOUT && key.layout == lay.revert_layout) {
+ gr_color(mCapsHighlightColor.red, mCapsHighlightColor.green, mCapsHighlightColor.blue, mCapsHighlightColor.alpha);
+ gr_fill(keyX, keyY, keyW, keyH);
+ }
+
+ // Highlight current key
+ if (hasHighlight && &key == currentKey && highlightRenderCount != 0) {
+ gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
+ gr_fill(keyX, keyY, keyW, keyH);
+ }
+ }
+ }
+
+ if (!hasHighlight || highlightRenderCount == 0)
+ mRendered = true;
+ else if (highlightRenderCount > 0)
+ highlightRenderCount--;
+ return 0;
+}
+
+int GUIKeyboard::Update(void)
+{
+ if (!isConditionTrue()) return (mRendered ? 2 : 0);
+ if (!mRendered) return 2;
+
+ return 0;
+}
+
+int GUIKeyboard::SetRenderPos(int x, int y, int w, int h)
+{
+ RenderObject::SetRenderPos(x, y, w, h);
+ SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+ return 0;
+}
+
+GUIKeyboard::Key* GUIKeyboard::HitTestKey(int x, int y)
+{
+ if (!IsInRegion(x, y))
+ return NULL;
+
+ int rely = y - mRenderY;
+ int relx = x - mRenderX;
+
+ Layout& lay = layouts[currentLayout - 1];
+
+ // Find the correct row
+ int row;
+ for (row = 0; row < MAX_KEYBOARD_ROWS; ++row) {
+ if (lay.row_end_y[row] > rely)
+ break;
+ }
+ if (row == MAX_KEYBOARD_ROWS)
+ return NULL;
+
+ // Find the correct key (column)
+ int col;
+ int x1 = 0;
+ for (col = 0; col < MAX_KEYBOARD_KEYS; ++col) {
+ Key& key = lay.keys[row][col];
+ if (x1 <= relx && relx < key.end_x && key.key != 0) {
+ // This is the key that was pressed!
+ return &key;
+ }
+ x1 = key.end_x;
+ }
+ return NULL;
+}
+
+int GUIKeyboard::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ static int was_held = 0, startX = 0;
+
+ if (!isConditionTrue()) return -1;
+
+ switch (state)
+ {
+ case TOUCH_START:
+ was_held = 0;
+ startX = x;
+ currentKey = HitTestKey(x, y);
+ if (currentKey)
+ highlightRenderCount = -1;
+ else
+ highlightRenderCount = 0;
+ mRendered = false;
+ break;
+
+ case TOUCH_DRAG:
+ break;
+
+ case TOUCH_RELEASE:
+ if (x < startX - (mRenderW * 0.5)) {
+ if (highlightRenderCount != 0) {
+ highlightRenderCount = 0;
+ mRendered = false;
+ }
+ PageManager::NotifyKeyboard(KEYBOARD_SWIPE_LEFT);
+ return 0;
+ } else if (x > startX + (mRenderW * 0.5)) {
+ if (highlightRenderCount != 0) {
+ highlightRenderCount = 0;
+ mRendered = false;
+ }
+ PageManager::NotifyKeyboard(KEYBOARD_SWIPE_RIGHT);
+ return 0;
+ }
+ // fall through
+ case TOUCH_HOLD:
+ case TOUCH_REPEAT:
+ if (!currentKey) {
+ if (highlightRenderCount != 0) {
+ highlightRenderCount = 0;
+ mRendered = false;
+ }
+ return 0;
+ }
+
+ if (highlightRenderCount != 0) {
+ if (state == TOUCH_RELEASE)
+ highlightRenderCount = 2;
+ else
+ highlightRenderCount = -1;
+ mRendered = false;
+ }
+
+ if (HitTestKey(x, y) != currentKey) {
+ // We dragged off of the starting key
+ currentKey = NULL;
+ if (highlightRenderCount != 0) {
+ highlightRenderCount = 0;
+ mRendered = false;
+ }
+ return 0;
+ } else {
+ Key& key = *currentKey;
+ Layout& lay = layouts[currentLayout - 1];
+ if (state == TOUCH_RELEASE && was_held == 0) {
+ DataManager::Vibrate("tw_keyboard_vibrate");
+ if ((int)key.key == KEYBOARD_LAYOUT) {
+ // Switch layouts
+ if (lay.is_caps && key.layout == lay.revert_layout && !CapsLockOn) {
+ CapsLockOn = true; // Set the caps lock
+ } else {
+ CapsLockOn = false; // Unset the caps lock and change layouts
+ currentLayout = key.layout;
+ }
+ mRendered = false;
+ } else if ((int)key.key == KEYBOARD_ACTION) {
+ // Action
+ highlightRenderCount = 0;
+ // Send action notification
+ PageManager::NotifyKeyboard(key.key);
+ } else if ((int)key.key < KEYBOARD_SPECIAL_KEYS && (int)key.key > 0) {
+ // Regular key
+ PageManager::NotifyKeyboard(key.key);
+ if (!CapsLockOn && lay.is_caps) {
+ // caps lock was not set, change layouts
+ currentLayout = lay.revert_layout;
+ mRendered = false;
+ }
+ }
+ } else if (state == TOUCH_HOLD) {
+ was_held = 1;
+ if ((int)key.key == KEYBOARD_BACKSPACE) {
+ // Repeat backspace
+ PageManager::NotifyKeyboard(key.key);
+ } else if ((int)key.longpresskey < KEYBOARD_SPECIAL_KEYS && (int)key.longpresskey > 0) {
+ // Long Press Key
+ DataManager::Vibrate("tw_keyboard_vibrate");
+ PageManager::NotifyKeyboard(key.longpresskey);
+ }
+ } else if (state == TOUCH_REPEAT) {
+ was_held = 1;
+ if ((int)key.key == KEYBOARD_BACKSPACE) {
+ // Repeat backspace
+ PageManager::NotifyKeyboard(key.key);
+ }
+ }
+ }
+ break;
+ }
+
+ return 0;
+}
diff --git a/gui/listbox.cpp b/gui/listbox.cpp
new file mode 100644
index 000000000..4c9a68ac8
--- /dev/null
+++ b/gui/listbox.cpp
@@ -0,0 +1,176 @@
+/*
+ Copyright 2013 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../data.hpp"
+
+GUIListBox::GUIListBox(xml_node<>* node) : GUIScrollList(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+ mIconSelected = mIconUnselected = NULL;
+ mUpdate = 0;
+
+ // Get the icons, if any
+ child = FindNode(node, "icon");
+ if (child) {
+ mIconSelected = LoadAttrImage(child, "selected");
+ mIconUnselected = LoadAttrImage(child, "unselected");
+ }
+ int iconWidth = std::max(mIconSelected->GetWidth(), mIconUnselected->GetWidth());
+ int iconHeight = std::max(mIconSelected->GetHeight(), mIconUnselected->GetHeight());
+ SetMaxIconSize(iconWidth, iconHeight);
+
+ // Handle the result variable
+ child = FindNode(node, "data");
+ if (child) {
+ attr = child->first_attribute("name");
+ if (attr)
+ mVariable = attr->value();
+ attr = child->first_attribute("default");
+ if (attr)
+ DataManager::SetValue(mVariable, attr->value());
+ // Get the currently selected value for the list
+ DataManager::GetValue(mVariable, currentValue);
+ }
+ else
+ allowSelection = false; // allows using listbox as a read-only list
+
+ // Get the data for the list
+ child = FindNode(node, "listitem");
+ if (!child) return;
+ while (child) {
+ ListData data;
+
+ attr = child->first_attribute("name");
+ if (!attr)
+ continue;
+ data.displayName = gui_parse_text(attr->value());
+ data.variableValue = gui_parse_text(child->value());
+ if (child->value() == currentValue) {
+ data.selected = 1;
+ } else {
+ data.selected = 0;
+ }
+ data.action = NULL;
+ xml_node<>* action = child->first_node("action");
+ if (action) {
+ data.action = new GUIAction(action);
+ allowSelection = true;
+ }
+
+ mList.push_back(data);
+
+ child = child->next_sibling("listitem");
+ }
+}
+
+GUIListBox::~GUIListBox()
+{
+}
+
+int GUIListBox::Update(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ GUIScrollList::Update();
+
+ if (mUpdate) {
+ mUpdate = 0;
+ if (Render() == 0)
+ return 2;
+ }
+ return 0;
+}
+
+int GUIListBox::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIScrollList::NotifyVarChange(varName, value);
+
+ if(!isConditionTrue())
+ return 0;
+
+ // Check to see if the variable that we are using to store the list selected value has been updated
+ if (varName == mVariable) {
+ int i, listSize = mList.size();
+
+ currentValue = value;
+
+ for (i = 0; i < listSize; i++) {
+ if (mList.at(i).variableValue == currentValue) {
+ mList.at(i).selected = 1;
+ SetVisibleListLocation(i);
+ } else
+ mList.at(i).selected = 0;
+ }
+ mUpdate = 1;
+ return 0;
+ }
+ return 0;
+}
+
+void GUIListBox::SetPageFocus(int inFocus)
+{
+ GUIScrollList::SetPageFocus(inFocus);
+ if (inFocus) {
+ DataManager::GetValue(mVariable, currentValue);
+ NotifyVarChange(mVariable, currentValue);
+ }
+}
+
+size_t GUIListBox::GetItemCount()
+{
+ return mList.size();
+}
+
+void GUIListBox::RenderItem(size_t itemindex, int yPos, bool selected)
+{
+ // note: the "selected" parameter above is for the currently touched item
+ // don't confuse it with the more persistent "selected" flag per list item used below
+ ImageResource* icon = mList.at(itemindex).selected ? mIconSelected : mIconUnselected;
+ const std::string& text = mList.at(itemindex).displayName;
+
+ RenderStdItem(yPos, selected, icon, text.c_str());
+}
+
+void GUIListBox::NotifySelect(size_t item_selected)
+{
+ for (size_t i = 0; i < mList.size(); i++) {
+ mList.at(i).selected = 0;
+ }
+ if (item_selected < mList.size()) {
+ ListData& data = mList.at(item_selected);
+ data.selected = 1;
+ string str = data.variableValue; // [check] should this set currentValue instead?
+ DataManager::SetValue(mVariable, str);
+ if (data.action)
+ data.action->doActions();
+ }
+ mUpdate = 1;
+}
diff --git a/gui/mousecursor.cpp b/gui/mousecursor.cpp
new file mode 100644
index 000000000..84e6322a4
--- /dev/null
+++ b/gui/mousecursor.cpp
@@ -0,0 +1,147 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+MouseCursor::MouseCursor(int resX, int resY)
+{
+ ResetData(resX, resY);
+}
+
+MouseCursor::~MouseCursor()
+{
+}
+
+void MouseCursor::ResetData(int resX, int resY)
+{
+ m_resX = resX;
+ m_resY = resY;
+ m_moved = false;
+ m_speedMultiplier = 2.5f;
+ m_image = NULL;
+ m_present = false;
+
+ ConvertStrToColor("red", &m_color);
+
+ SetRenderPos(resX/2, resY/2, 10, 10);
+}
+
+void MouseCursor::LoadData(xml_node<>* node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ child = FindNode(node, "placement");
+ if(child)
+ LoadPlacement(child, &mRenderX, &mRenderY, &mRenderW, &mRenderH);
+
+ child = FindNode(node, "background");
+ if(child)
+ {
+ m_color = LoadAttrColor(child, "color", m_color);
+ m_image = LoadAttrImage(child, "resource");
+ if(m_image)
+ {
+ mRenderW = m_image->GetWidth();
+ mRenderH = m_image->GetHeight();
+ }
+ }
+
+ child = FindNode(node, "speed");
+ if(child)
+ {
+ attr = child->first_attribute("multiplier");
+ if(attr)
+ m_speedMultiplier = atof(attr->value());
+ }
+}
+
+int MouseCursor::Render(void)
+{
+ if(!m_present)
+ return 0;
+
+ if(m_image)
+ {
+ gr_blit(m_image->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
+ }
+ else
+ {
+ gr_color(m_color.red, m_color.green, m_color.blue, m_color.alpha);
+ gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
+ }
+ return 0;
+}
+
+int MouseCursor::Update(void)
+{
+ if(m_present != ev_has_mouse())
+ {
+ m_present = ev_has_mouse();
+ if(m_present)
+ SetRenderPos(m_resX/2, m_resY/2);
+ return 2;
+ }
+
+ if(m_present && m_moved)
+ {
+ m_moved = false;
+ return 2;
+ }
+ return 0;
+}
+
+int MouseCursor::SetRenderPos(int x, int y, int w, int h)
+{
+ if(x == mRenderX && y == mRenderY)
+ m_moved = true;
+
+ return RenderObject::SetRenderPos(x, y, w, h);
+}
+
+void MouseCursor::Move(int deltaX, int deltaY)
+{
+ if(deltaX != 0)
+ {
+ mRenderX += deltaX*m_speedMultiplier;
+ mRenderX = (std::min)(mRenderX, m_resX);
+ mRenderX = (std::max)(mRenderX, 0);
+
+ m_moved = true;
+ }
+
+ if(deltaY != 0)
+ {
+ mRenderY += deltaY*m_speedMultiplier;
+ mRenderY = (std::min)(mRenderY, m_resY);
+ mRenderY = (std::max)(mRenderY, 0);
+
+ m_moved = true;
+ }
+}
+
+void MouseCursor::GetPos(int& x, int& y)
+{
+ x = mRenderX;
+ y = mRenderY;
+}
diff --git a/gui/object.cpp b/gui/object.cpp
new file mode 100644
index 000000000..7cce5db8b
--- /dev/null
+++ b/gui/object.cpp
@@ -0,0 +1,210 @@
+// checkbox.cpp - GUICheckbox object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+#include "../variables.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../data.hpp"
+
+GUIObject::GUIObject(xml_node<>* node)
+{
+ mConditionsResult = true;
+
+ // Break out early, it's too hard to check if valid every step
+ if (!node) return;
+
+ // First, get the action
+ xml_node<>* condition = FindNode(node, "conditions");
+ if (condition) condition = FindNode(condition, "condition");
+ else condition = FindNode(node, "condition");
+
+ if (!condition) return;
+
+ while (condition)
+ {
+ Condition cond;
+
+ cond.mCompareOp = "=";
+
+ xml_attribute<>* attr;
+ attr = condition->first_attribute("var1");
+ if (attr) cond.mVar1 = attr->value();
+
+ attr = condition->first_attribute("op");
+ if (attr) cond.mCompareOp = attr->value();
+
+ attr = condition->first_attribute("var2");
+ if (attr) cond.mVar2 = attr->value();
+
+ mConditions.push_back(cond);
+
+ condition = condition->next_sibling("condition");
+ }
+}
+
+GUIObject::~GUIObject()
+{
+}
+
+bool GUIObject::IsConditionVariable(std::string var)
+{
+ std::vector<Condition>::iterator iter;
+ for (iter = mConditions.begin(); iter != mConditions.end(); iter++)
+ {
+ if (iter->mVar1 == var)
+ return true;
+ }
+ return false;
+}
+
+bool GUIObject::isConditionTrue()
+{
+ return mConditionsResult;
+}
+
+bool GUIObject::isConditionTrue(Condition* condition)
+{
+ // This is used to hold the proper value of "true" based on the '!' NOT flag
+ bool bTrue = true;
+
+ if (condition->mVar1.empty())
+ return bTrue;
+
+ if (!condition->mCompareOp.empty() && condition->mCompareOp[0] == '!')
+ bTrue = false;
+
+ if (condition->mVar2.empty() && condition->mCompareOp != "modified")
+ {
+ if (!DataManager::GetStrValue(condition->mVar1).empty())
+ return bTrue;
+
+ return !bTrue;
+ }
+
+ string var1, var2;
+ if (DataManager::GetValue(condition->mVar1, var1))
+ var1 = condition->mVar1;
+ if (DataManager::GetValue(condition->mVar2, var2))
+ var2 = condition->mVar2;
+
+ // This is a special case, we stat the file and that determines our result
+ if (var1 == "fileexists")
+ {
+ struct stat st;
+ if (stat(var2.c_str(), &st) == 0)
+ var2 = var1;
+ else
+ var2 = "FAILED";
+ }
+ if (var1 == "mounted")
+ {
+ if (isMounted(condition->mVar2))
+ var2 = var1;
+ else
+ var2 = "FAILED";
+ }
+
+ if (condition->mCompareOp.find('=') != string::npos && var1 == var2)
+ return bTrue;
+
+ if (condition->mCompareOp.find('>') != string::npos && (atof(var1.c_str()) > atof(var2.c_str())))
+ return bTrue;
+
+ if (condition->mCompareOp.find('<') != string::npos && (atof(var1.c_str()) < atof(var2.c_str())))
+ return bTrue;
+
+ if (condition->mCompareOp == "modified")
+ {
+ // This is a hack to allow areas to reset the default value
+ if (var1.empty())
+ {
+ condition->mLastVal = var1;
+ return !bTrue;
+ }
+
+ if (var1 != condition->mLastVal)
+ return bTrue;
+ }
+
+ return !bTrue;
+}
+
+bool GUIObject::isConditionValid()
+{
+ return !mConditions.empty();
+}
+
+int GUIObject::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ mConditionsResult = true;
+
+ const bool varNameEmpty = varName.empty();
+ std::vector<Condition>::iterator iter;
+ for (iter = mConditions.begin(); iter != mConditions.end(); ++iter)
+ {
+ if(varNameEmpty && iter->mCompareOp == "modified")
+ {
+ string val;
+
+ // If this fails, val will not be set, which is perfect
+ if (DataManager::GetValue(iter->mVar1, val))
+ {
+ DataManager::SetValue(iter->mVar1, "");
+ DataManager::GetValue(iter->mVar1, val);
+ }
+ iter->mLastVal = val;
+ }
+
+ if(varNameEmpty || iter->mVar1 == varName || iter->mVar2 == varName)
+ iter->mLastResult = isConditionTrue(&(*iter));
+
+ if(!iter->mLastResult)
+ mConditionsResult = false;
+ }
+ return 0;
+}
+
+bool GUIObject::isMounted(string vol)
+{
+ FILE *fp;
+ char tmpOutput[255];
+
+ fp = fopen("/proc/mounts", "rt");
+ while (fgets(tmpOutput,255,fp) != NULL)
+ {
+ char* mnt = tmpOutput;
+ while (*mnt > 32) mnt++;
+ while (*mnt > 0 && *mnt <= 32) mnt++;
+ char* pos = mnt;
+ while (*pos > 32) pos++;
+ *pos = 0;
+ if (vol == mnt)
+ {
+ fclose(fp);
+ return true;
+ }
+ }
+ fclose(fp);
+ return false;
+}
diff --git a/gui/objects.hpp b/gui/objects.hpp
new file mode 100644
index 000000000..f8569d6ea
--- /dev/null
+++ b/gui/objects.hpp
@@ -0,0 +1,1157 @@
+/*
+ Copyright 2013 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// objects.hpp - Base classes for object manager of GUI
+
+#ifndef _OBJECTS_HEADER
+#define _OBJECTS_HEADER
+
+#include "rapidxml.hpp"
+#include <vector>
+#include <string>
+#include <map>
+#include <set>
+#include <time.h>
+
+using namespace rapidxml;
+
+#include "../data.hpp"
+#include "resources.hpp"
+#include "pages.hpp"
+#include "../partitions.hpp"
+
+#ifndef TW_X_OFFSET
+#define TW_X_OFFSET 0
+#endif
+#ifndef TW_Y_OFFSET
+#define TW_Y_OFFSET 0
+#endif
+
+class RenderObject
+{
+public:
+ enum Placement {
+ TOP_LEFT = 0,
+ TOP_RIGHT = 1,
+ BOTTOM_LEFT = 2,
+ BOTTOM_RIGHT = 3,
+ CENTER = 4,
+ CENTER_X_ONLY = 5,
+ };
+
+public:
+ RenderObject() { mRenderX = 0; mRenderY = 0; mRenderW = 0; mRenderH = 0; mPlacement = TOP_LEFT; }
+ virtual ~RenderObject() {}
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void) = 0;
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void) { return 0; }
+
+ // GetRenderPos - Returns the current position of the object
+ virtual int GetRenderPos(int& x, int& y, int& w, int& h) { x = mRenderX; y = mRenderY; w = mRenderW; h = mRenderH; return 0; }
+
+ // SetRenderPos - Update the position of the object
+ // Return 0 on success, <0 on error
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0) { mRenderX = x; mRenderY = y; if (w || h) { mRenderW = w; mRenderH = h; } return 0; }
+
+ // GetPlacement - Returns the current placement
+ virtual int GetPlacement(Placement& placement) { placement = mPlacement; return 0; }
+
+ // SetPlacement - Update the current placement
+ virtual int SetPlacement(Placement placement) { mPlacement = placement; return 0; }
+
+ // SetPageFocus - Notify when a page gains or loses focus
+ virtual void SetPageFocus(int inFocus) { return; }
+
+protected:
+ int mRenderX, mRenderY, mRenderW, mRenderH;
+ Placement mPlacement;
+};
+
+class ActionObject
+{
+public:
+ ActionObject() { mActionX = 0; mActionY = 0; mActionW = 0; mActionH = 0; }
+ virtual ~ActionObject() {}
+
+public:
+ // NotifyTouch - Notify of a touch event
+ // Return 0 on success, >0 to ignore remainder of touch, and <0 on error
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y) { return 0; }
+
+ // NotifyKey - Notify of a key press
+ // Return 0 on success (and consume key), >0 to pass key to next handler, and <0 on error
+ virtual int NotifyKey(int key, bool down) { return 1; }
+
+ // GetRenderPos - Returns the current position of the object
+ virtual int GetActionPos(int& x, int& y, int& w, int& h) { x = mActionX; y = mActionY; w = mActionW; h = mActionH; return 0; }
+
+ // SetRenderPos - Update the position of the object
+ // Return 0 on success, <0 on error
+ virtual int SetActionPos(int x, int y, int w = 0, int h = 0);
+
+ // IsInRegion - Checks if the request is handled by this object
+ // Return 1 if this object handles the request, 0 if not
+ virtual int IsInRegion(int x, int y) { return ((x < mActionX || x >= mActionX + mActionW || y < mActionY || y >= mActionY + mActionH) ? 0 : 1); }
+
+protected:
+ int mActionX, mActionY, mActionW, mActionH;
+};
+
+class GUIObject
+{
+public:
+ GUIObject(xml_node<>* node);
+ virtual ~GUIObject();
+
+public:
+ bool IsConditionVariable(std::string var);
+ bool isConditionTrue();
+ bool isConditionValid();
+
+ // NotifyVarChange - Notify of a variable change
+ // Returns 0 on success, <0 on error
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+protected:
+ class Condition
+ {
+ public:
+ Condition() {
+ mLastResult = true;
+ }
+
+ std::string mVar1;
+ std::string mVar2;
+ std::string mCompareOp;
+ std::string mLastVal;
+ bool mLastResult;
+ };
+
+ std::vector<Condition> mConditions;
+
+protected:
+ bool isMounted(std::string vol);
+ bool isConditionTrue(Condition* condition);
+
+ bool mConditionsResult;
+};
+
+class InputObject
+{
+public:
+ InputObject() { HasInputFocus = 0; }
+ virtual ~InputObject() {}
+
+public:
+ // NotifyKeyboard - Notify of keyboard input
+ // Return 0 on success (and consume key), >0 to pass key to next handler, and <0 on error
+ virtual int NotifyKeyboard(int key) { return 1; }
+
+ virtual int SetInputFocus(int focus) { HasInputFocus = focus; return 1; }
+
+protected:
+ int HasInputFocus;
+};
+
+// Derived Objects
+// GUIText - Used for static text
+class GUIText : public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ // w and h may be ignored, in which case, no bounding box is applied
+ GUIText(xml_node<>* node);
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // Retrieve the size of the current string (dynamic strings may change per call)
+ virtual int GetCurrentBounds(int& w, int& h);
+
+ // Notify of a variable change
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+ // Set maximum width in pixels
+ virtual int SetMaxWidth(unsigned width);
+
+ // Set number of characters to skip (for scrolling)
+ virtual int SkipCharCount(unsigned skip);
+
+public:
+ bool isHighlighted;
+
+protected:
+ std::string mText;
+ std::string mLastValue;
+ COLOR mColor;
+ COLOR mHighlightColor;
+ FontResource* mFont;
+ int mIsStatic;
+ int mVarChanged;
+ int mFontHeight;
+ unsigned maxWidth;
+ unsigned charSkip;
+};
+
+// GUIImage - Used for static image
+class GUIImage : public GUIObject, public RenderObject
+{
+public:
+ GUIImage(xml_node<>* node);
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // SetRenderPos - Update the position of the object
+ // Return 0 on success, <0 on error
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+public:
+ bool isHighlighted;
+
+protected:
+ ImageResource* mImage;
+ ImageResource* mHighlightImage;
+};
+
+// GUIFill - Used for fill colors
+class GUIFill : public GUIObject, public RenderObject
+{
+public:
+ GUIFill(xml_node<>* node);
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+protected:
+ COLOR mColor;
+};
+
+// GUIAction - Used for standard actions
+class GUIAction : public GUIObject, public ActionObject
+{
+ friend class ActionThread;
+
+public:
+ GUIAction(xml_node<>* node);
+
+public:
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+ virtual int NotifyKey(int key, bool down);
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+ int doActions();
+
+protected:
+ class Action
+ {
+ public:
+ std::string mFunction;
+ std::string mArg;
+ };
+
+ std::vector<Action> mActions;
+ std::map<int, bool> mKeys;
+
+protected:
+ enum ThreadType { THREAD_NONE, THREAD_ACTION, THREAD_CANCEL };
+
+ int getKeyByName(std::string key);
+ int doAction(Action action);
+ ThreadType getThreadType(const Action& action);
+ void simulate_progress_bar(void);
+ int flash_zip(std::string filename, int* wipe_cache);
+ void reinject_after_flash();
+ void operation_start(const string operation_name);
+ void operation_end(const int operation_status);
+ time_t Start;
+
+ // map action name to function pointer
+ typedef int (GUIAction::*execFunction)(std::string);
+ typedef std::map<std::string, execFunction> mapFunc;
+ static mapFunc mf;
+ static std::set<std::string> setActionsRunningInCallerThread;
+
+ // GUI actions
+ int reboot(std::string arg);
+ int home(std::string arg);
+ int key(std::string arg);
+ int page(std::string arg);
+ int reload(std::string arg);
+ int readBackup(std::string arg);
+ int set(std::string arg);
+ int clear(std::string arg);
+ int mount(std::string arg);
+ int unmount(std::string arg);
+ int restoredefaultsettings(std::string arg);
+ int copylog(std::string arg);
+ int compute(std::string arg);
+ int setguitimezone(std::string arg);
+ int overlay(std::string arg);
+ int queuezip(std::string arg);
+ int cancelzip(std::string arg);
+ int queueclear(std::string arg);
+ int sleep(std::string arg);
+ int appenddatetobackupname(std::string arg);
+ int generatebackupname(std::string arg);
+ int checkpartitionlist(std::string arg);
+ int getpartitiondetails(std::string arg);
+ int screenshot(std::string arg);
+ int setbrightness(std::string arg);
+
+ // (originally) threaded actions
+ int fileexists(std::string arg);
+ int flash(std::string arg);
+ int wipe(std::string arg);
+ int refreshsizes(std::string arg);
+ int nandroid(std::string arg);
+ int fixpermissions(std::string arg);
+ int dd(std::string arg);
+ int partitionsd(std::string arg);
+ int installhtcdumlock(std::string arg);
+ int htcdumlockrestoreboot(std::string arg);
+ int htcdumlockreflashrecovery(std::string arg);
+ int cmd(std::string arg);
+ int terminalcommand(std::string arg);
+ int killterminal(std::string arg);
+ int reinjecttwrp(std::string arg);
+ int checkbackupname(std::string arg);
+ int decrypt(std::string arg);
+ int adbsideload(std::string arg);
+ int adbsideloadcancel(std::string arg);
+ int openrecoveryscript(std::string arg);
+ int installsu(std::string arg);
+ int fixsu(std::string arg);
+ int decrypt_backup(std::string arg);
+ int repair(std::string arg);
+ int resize(std::string arg);
+ int changefilesystem(std::string arg);
+ int startmtp(std::string arg);
+ int stopmtp(std::string arg);
+ int flashimage(std::string arg);
+ int cancelbackup(std::string arg);
+ int checkpartitionlifetimewrites(std::string arg);
+ int mountsystemtoggle(std::string arg);
+
+ int simulate;
+};
+
+class GUIButton : public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ GUIButton(xml_node<>* node);
+ virtual ~GUIButton();
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // SetPos - Update the position of the render object
+ // Return 0 on success, <0 on error
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+ // NotifyTouch - Notify of a touch event
+ // Return 0 on success, >0 to ignore remainder of touch, and <0 on error
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+
+protected:
+ GUIImage* mButtonImg;
+ ImageResource* mButtonIcon;
+ GUIText* mButtonLabel;
+ GUIAction* mAction;
+ int mTextX, mTextY, mTextW, mTextH;
+ int mIconX, mIconY, mIconW, mIconH;
+ bool mRendered;
+ bool hasHighlightColor;
+ bool renderHighlight;
+ bool hasFill;
+ COLOR mFillColor;
+ COLOR mHighlightColor;
+ Placement TextPlacement;
+};
+
+class GUICheckbox: public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ GUICheckbox(xml_node<>* node);
+ virtual ~GUICheckbox();
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // SetPos - Update the position of the render object
+ // Return 0 on success, <0 on error
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+ // NotifyTouch - Notify of a touch event
+ // Return 0 on success, >0 to ignore remainder of touch, and <0 on error
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+
+protected:
+ ImageResource* mChecked;
+ ImageResource* mUnchecked;
+ GUIText* mLabel;
+ int mTextX, mTextY;
+ int mCheckX, mCheckY, mCheckW, mCheckH;
+ int mLastState;
+ bool mRendered;
+ std::string mVarName;
+};
+
+class GUIScrollList : public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ GUIScrollList(xml_node<>* node);
+ virtual ~GUIScrollList();
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // NotifyTouch - Notify of a touch event
+ // Return 0 on success, >0 to ignore remainder of touch, and <0 on error
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+
+ // NotifyVarChange - Notify of a variable change
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+ // SetPos - Update the position of the render object
+ // Return 0 on success, <0 on error
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+ // SetPageFocus - Notify when a page gains or loses focus
+ virtual void SetPageFocus(int inFocus);
+
+protected:
+ // derived classes need to implement these
+ // get number of items
+ virtual size_t GetItemCount() { return 0; }
+ // render a single item in rect (mRenderX, yPos, mRenderW, actualItemHeight)
+ virtual void RenderItem(size_t itemindex, int yPos, bool selected);
+ // an item was selected
+ virtual void NotifySelect(size_t item_selected) {}
+
+ // render a standard-layout list item with optional icon and text
+ void RenderStdItem(int yPos, bool selected, ImageResource* icon, const char* text, int iconAndTextH = 0);
+
+ enum { NO_ITEM = (size_t)-1 };
+ // returns item index at coordinates or NO_ITEM if there is no item there
+ size_t HitTestItem(int x, int y);
+
+ // Called by the derived class to set the max icon size so we can calculate the proper actualItemHeight and center smaller icons if the icon size varies
+ void SetMaxIconSize(int w, int h);
+
+ // This will make sure that the item indicated by list_index is visible on the screen
+ void SetVisibleListLocation(size_t list_index);
+
+ // Handle scrolling changes for drags and kinetic scrolling
+ void HandleScrolling();
+
+ // Returns many full rows the list is capable of displaying
+ int GetDisplayItemCount();
+
+ // Returns the size in pixels of a partial item or row size
+ int GetDisplayRemainder();
+
+protected:
+ // Background
+ COLOR mBackgroundColor;
+ ImageResource* mBackground; // background image, if any, automatically centered
+
+ // Header
+ COLOR mHeaderBackgroundColor;
+ COLOR mHeaderFontColor;
+ std::string mHeaderText; // Original header text without parsing any variables
+ std::string mLastHeaderValue; // Header text after parsing variables
+ bool mHeaderIsStatic; // indicates if the header is static (no need to check for changes in NotifyVarChange)
+ int mHeaderH; // actual header height including font, icon, padding, and separator heights
+ ImageResource* mHeaderIcon;
+ int mHeaderIconHeight, mHeaderIconWidth; // width and height of the header icon if present
+ int mHeaderSeparatorH; // Height of the separator between header and list items
+ COLOR mHeaderSeparatorColor; // color of the header separator
+
+ // Per-item layout
+ FontResource* mFont;
+ COLOR mFontColor;
+ bool hasHighlightColor; // indicates if a highlight color was set
+ COLOR mHighlightColor; // background row highlight color
+ COLOR mFontHighlightColor;
+ int mFontHeight;
+ int actualItemHeight; // Actual height of each item in pixels including max icon size, font size, and padding
+ int maxIconWidth, maxIconHeight; // max icon width and height for the list, set by derived class in SetMaxIconSize
+ int mItemSpacing; // stores the spacing or padding on the y axis, part of the actualItemHeight
+ int mSeparatorH; // Height of the separator between items
+ COLOR mSeparatorColor; // color of the separator that is between items
+
+ // Scrollbar
+ int mFastScrollW; // width of the fastscroll area
+ int mFastScrollLineW; // width of the line for fastscroll rendering
+ int mFastScrollRectW; // width of the rectangle for fastscroll
+ int mFastScrollRectH; // minimum height of the rectangle for fastscroll
+ COLOR mFastScrollLineColor;
+ COLOR mFastScrollRectColor;
+
+ // Scrolling and dynamic state
+ int mFastScrollRectCurrentY; // current top of fastscroll rect relative to list top
+ int mFastScrollRectCurrentH; // current height of fastscroll rect
+ int mFastScrollRectTouchY; // offset from top of fastscroll rect where the user initially touched
+ bool hasScroll; // indicates that we have enough items in the list to scroll
+ int firstDisplayedItem; // this item goes at the top of the display list - may only be partially visible
+ int scrollingSpeed; // on a touch release, this is set based on the difference in the y-axis between the last 2 touches and indicates how fast the kinetic scrolling will go
+ int y_offset; // this is how many pixels offset in the y axis for per pixel scrolling, is always <= 0 and should never be < -actualItemHeight
+ bool allowSelection; // true if touched item can be selected, false for pure read-only lists and the console
+ size_t selectedItem; // selected item index after the initial touch, set to -1 if we are scrolling
+ int touchDebounce; // debounce for touches, minimum of 6 pixels but may be larger calculated based actualItemHeight / 3
+ int lastY, last2Y; // last 2 touch locations, used for tracking kinetic scroll speed
+ int fastScroll; // indicates that the inital touch was inside the fastscroll region - makes for easier fast scrolling as the touches don't have to stay within the fast scroll region and you drag your finger
+ int mUpdate; // indicates that a change took place and we need to re-render
+};
+
+class GUIFileSelector : public GUIScrollList
+{
+public:
+ GUIFileSelector(xml_node<>* node);
+ virtual ~GUIFileSelector();
+
+public:
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // NotifyVarChange - Notify of a variable change
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+ // SetPageFocus - Notify when a page gains or loses focus
+ virtual void SetPageFocus(int inFocus);
+
+ virtual size_t GetItemCount();
+ virtual void RenderItem(size_t itemindex, int yPos, bool selected);
+ virtual void NotifySelect(size_t item_selected);
+
+protected:
+ struct FileData {
+ std::string fileName;
+ unsigned char fileType; // Uses d_type format from struct dirent
+ mode_t protection; // Uses mode_t format from stat
+ uid_t userId;
+ gid_t groupId;
+ off_t fileSize;
+ time_t lastAccess; // Uses time_t format from stat
+ time_t lastModified; // Uses time_t format from stat
+ time_t lastStatChange; // Uses time_t format from stat
+ };
+
+protected:
+ virtual int GetFileList(const std::string folder);
+ static bool fileSort(FileData d1, FileData d2);
+
+protected:
+ std::vector<FileData> mFolderList;
+ std::vector<FileData> mFileList;
+ std::string mPathVar; // current path displayed, saved in the data manager
+ std::string mPathDefault; // default value for the path if none is set in mPathVar
+ std::string mExtn; // used for filtering the file list, for example, *.zip
+ std::string mVariable; // set when the user selects an item, pull path like /path/to/foo
+ std::string mSortVariable; // data manager variable used to change the sorting of files
+ std::string mSelection; // set when the user selects an item without the full path like selecting /path/to/foo would just be set to foo
+ int mShowFolders, mShowFiles; // indicates if the list should show folders and/or files
+ int mShowNavFolders; // indicates if the list should include the "up a level" item and allow you to traverse folders (nav folders are disabled for the restore list, for instance)
+ static int mSortOrder; // must be static because it is used by the static function fileSort
+ ImageResource* mFolderIcon;
+ ImageResource* mFileIcon;
+ bool updateFileList;
+};
+
+class GUIListBox : public GUIScrollList
+{
+public:
+ GUIListBox(xml_node<>* node);
+ virtual ~GUIListBox();
+
+public:
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // NotifyVarChange - Notify of a variable change
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+ // SetPageFocus - Notify when a page gains or loses focus
+ virtual void SetPageFocus(int inFocus);
+
+ virtual size_t GetItemCount();
+ virtual void RenderItem(size_t itemindex, int yPos, bool selected);
+ virtual void NotifySelect(size_t item_selected);
+
+protected:
+ struct ListData {
+ std::string displayName;
+ std::string variableValue;
+ unsigned int selected;
+ GUIAction* action;
+ };
+
+protected:
+ std::vector<ListData> mList;
+ std::string mVariable;
+ std::string currentValue;
+ ImageResource* mIconSelected;
+ ImageResource* mIconUnselected;
+};
+
+class GUIPartitionList : public GUIScrollList
+{
+public:
+ GUIPartitionList(xml_node<>* node);
+ virtual ~GUIPartitionList();
+
+public:
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update();
+
+ // NotifyVarChange - Notify of a variable change
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+ // SetPageFocus - Notify when a page gains or loses focus
+ virtual void SetPageFocus(int inFocus);
+
+ virtual size_t GetItemCount();
+ virtual void RenderItem(size_t itemindex, int yPos, bool selected);
+ virtual void NotifySelect(size_t item_selected);
+
+protected:
+ void MatchList();
+ void SetPosition();
+
+protected:
+ std::vector<PartitionList> mList;
+ std::string ListType;
+ std::string mVariable;
+ std::string selectedList;
+ std::string currentValue;
+ std::string mLastValue;
+ ImageResource* mIconSelected;
+ ImageResource* mIconUnselected;
+ bool updateList;
+};
+
+class GUIConsole : public GUIScrollList
+{
+public:
+ GUIConsole(xml_node<>* node);
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // IsInRegion - Checks if the request is handled by this object
+ // Return 1 if this object handles the request, 0 if not
+ virtual int IsInRegion(int x, int y);
+
+ // NotifyTouch - Notify of a touch event
+ // Return 0 on success, >0 to ignore remainder of touch, and <0 on error (Return error to allow other handlers)
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+
+ // ScrollList interface
+ virtual size_t GetItemCount();
+ virtual void RenderItem(size_t itemindex, int yPos, bool selected);
+ virtual void NotifySelect(size_t item_selected);
+protected:
+ enum SlideoutState
+ {
+ hidden = 0,
+ visible,
+ request_hide,
+ request_show
+ };
+
+ ImageResource* mSlideoutImage;
+ size_t mLastCount; // lines from gConsole that are already split and copied into rConsole
+ bool scrollToEnd; // true if we want to keep tracking the last line
+ int mSlideoutX, mSlideoutY, mSlideoutW, mSlideoutH;
+ int mSlideout;
+ SlideoutState mSlideoutState;
+ std::vector<std::string> rConsole;
+ std::vector<std::string> rConsoleColor;
+
+protected:
+ bool AddLines();
+ int RenderSlideout(void);
+ int RenderConsole(void);
+};
+
+// GUIAnimation - Used for animations
+class GUIAnimation : public GUIObject, public RenderObject
+{
+public:
+ GUIAnimation(xml_node<>* node);
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+protected:
+ AnimationResource* mAnimation;
+ int mFrame;
+ int mFPS;
+ int mLoop;
+ int mRender;
+ int mUpdateCount;
+};
+
+class GUIProgressBar : public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ GUIProgressBar(xml_node<>* node);
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // NotifyVarChange - Notify of a variable change
+ // Returns 0 on success, <0 on error
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+protected:
+ ImageResource* mEmptyBar;
+ ImageResource* mFullBar;
+ std::string mMinValVar;
+ std::string mMaxValVar;
+ std::string mCurValVar;
+ float mSlide;
+ float mSlideInc;
+ int mSlideFrames;
+ int mLastPos;
+
+protected:
+ virtual int RenderInternal(void); // Does the actual render
+};
+
+class GUISlider : public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ GUISlider(xml_node<>* node);
+ virtual ~GUISlider();
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // NotifyTouch - Notify of a touch event
+ // Return 0 on success, >0 to ignore remainder of touch, and <0 on error
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+
+protected:
+ GUIAction* sAction;
+ GUIText* sSliderLabel;
+ ImageResource* sSlider;
+ ImageResource* sSliderUsed;
+ ImageResource* sTouch;
+ int sTouchW, sTouchH;
+ int sCurTouchX;
+ int sUpdate;
+};
+
+#define KEYBOARD_ACTION 253
+#define KEYBOARD_LAYOUT 254
+#define KEYBOARD_SWIPE_LEFT 252
+#define KEYBOARD_SWIPE_RIGHT 251
+#define KEYBOARD_ARROW_LEFT 250
+#define KEYBOARD_ARROW_RIGHT 249
+#define KEYBOARD_HOME 248
+#define KEYBOARD_END 247
+#define KEYBOARD_ARROW_UP 246
+#define KEYBOARD_ARROW_DOWN 245
+#define KEYBOARD_SPECIAL_KEYS 245
+#define KEYBOARD_BACKSPACE 8
+
+class GUIKeyboard : public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ GUIKeyboard(xml_node<>* node);
+ virtual ~GUIKeyboard();
+
+public:
+ virtual int Render(void);
+ virtual int Update(void);
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+protected:
+ struct Key
+ {
+ unsigned char key; // ASCII code or one of the special KEYBOARD_* codes above
+ unsigned char longpresskey;
+ int end_x;
+ int layout;
+ };
+ int ParseKey(const char* keyinfo, Key& key, int& Xindex, int keyWidth, bool longpress);
+ void LoadKeyLabels(xml_node<>* parent, int layout);
+ void DrawKey(Key& key, int keyX, int keyY, int keyW, int keyH);
+
+ enum {
+ MAX_KEYBOARD_LAYOUTS = 5,
+ MAX_KEYBOARD_ROWS = 9,
+ MAX_KEYBOARD_KEYS = 20
+ };
+ struct Layout
+ {
+ ImageResource* keyboardImg;
+ struct Key keys[MAX_KEYBOARD_ROWS][MAX_KEYBOARD_KEYS];
+ int row_end_y[MAX_KEYBOARD_ROWS];
+ bool is_caps;
+ int revert_layout;
+ };
+ Layout layouts[MAX_KEYBOARD_LAYOUTS];
+
+ struct KeyLabel
+ {
+ unsigned char key; // same as in struct Key
+ int layout_from; // 1-based; 0 for labels that apply to all layouts
+ int layout_to; // same as Key.layout
+ string text; // key label text
+ ImageResource* image; // image (overrides text if defined)
+ };
+ std::vector<KeyLabel> mKeyLabels;
+
+ // Find key at screen coordinates
+ Key* HitTestKey(int x, int y);
+
+ bool mRendered;
+ std::string mVariable;
+ int currentLayout;
+ bool CapsLockOn;
+ int highlightRenderCount;
+ Key* currentKey;
+ bool hasHighlight, hasCapsHighlight;
+ COLOR mHighlightColor;
+ COLOR mCapsHighlightColor;
+ COLOR mFontColor; // for centered key labels
+ COLOR mFontColorSmall; // for centered key labels
+ FontResource* mFont; // for main key labels
+ FontResource* mSmallFont; // for key labels like "?123"
+ FontResource* mLongpressFont; // for the small longpress label in the upper right corner
+ int longpressOffsetX, longpressOffsetY; // distance of the longpress label from the key corner
+ COLOR mLongpressFontColor;
+ COLOR mBackgroundColor; // keyboard background color
+ COLOR mKeyColorAlphanumeric; // key background color
+ COLOR mKeyColorOther; // key background color
+ int mKeyMarginX, mKeyMarginY; // space around key boxes - applied to left/right and top/bottom
+};
+
+// GUIInput - Used for keyboard input
+class GUIInput : public GUIObject, public RenderObject, public ActionObject, public InputObject
+{
+public:
+ GUIInput(xml_node<>* node);
+ virtual ~GUIInput();
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // Notify of a variable change
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+ // NotifyTouch - Notify of a touch event
+ // Return 0 on success, >0 to ignore remainder of touch, and <0 on error
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+
+ virtual int NotifyKeyboard(int key);
+
+protected:
+ virtual int GetSelection(int x, int y);
+
+ // Handles displaying the text properly when chars are added, deleted, or for scrolling
+ virtual int HandleTextLocation(int x);
+
+protected:
+ GUIText* mInputText;
+ GUIAction* mAction;
+ ImageResource* mBackground;
+ ImageResource* mCursor;
+ FontResource* mFont;
+ std::string mText;
+ std::string mLastValue;
+ std::string mVariable;
+ std::string mMask;
+ std::string mMaskVariable;
+ COLOR mBackgroundColor;
+ COLOR mCursorColor;
+ int scrollingX;
+ int lastX;
+ int mCursorLocation;
+ int mBackgroundX, mBackgroundY, mBackgroundW, mBackgroundH;
+ int mFontY;
+ unsigned skipChars;
+ unsigned mFontHeight;
+ unsigned CursorWidth;
+ bool mRendered;
+ bool HasMask;
+ bool DrawCursor;
+ bool isLocalChange;
+ bool HasAllowed;
+ bool HasDisabled;
+ std::string AllowedList;
+ std::string DisabledList;
+ unsigned MinLen;
+ unsigned MaxLen;
+};
+
+class HardwareKeyboard
+{
+public:
+ HardwareKeyboard();
+ virtual ~HardwareKeyboard();
+
+public:
+ // called by the input handler for key events
+ int KeyDown(int key_code);
+ int KeyUp(int key_code);
+
+ // called by the input handler when holding a key down
+ int KeyRepeat();
+
+ // called by multi-key actions to suppress key-release notifications
+ void ConsumeKeyRelease(int key);
+
+private:
+ int mLastKeyChar;
+ std::set<int> mPressedKeys;
+};
+
+class GUISliderValue: public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ GUISliderValue(xml_node<>* node);
+ virtual ~GUISliderValue();
+
+public:
+ // Render - Render the full object to the GL surface
+ // Return 0 on success, <0 on error
+ virtual int Render(void);
+
+ // Update - Update any UI component animations (called <= 30 FPS)
+ // Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
+ virtual int Update(void);
+
+ // SetPos - Update the position of the render object
+ // Return 0 on success, <0 on error
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+ // NotifyTouch - Notify of a touch event
+ // Return 0 on success, >0 to ignore remainder of touch, and <0 on error
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+
+ // Notify of a variable change
+ virtual int NotifyVarChange(const std::string& varName, const std::string& value);
+
+ // SetPageFocus - Notify when a page gains or loses focus
+ virtual void SetPageFocus(int inFocus);
+
+protected:
+ int measureText(const std::string& str);
+ int valueFromPct(float pct);
+ float pctFromValue(int value);
+ void loadValue(bool force = false);
+
+ std::string mVariable;
+ int mMax;
+ int mMin;
+ int mValue;
+ char *mValueStr;
+ float mValuePct;
+ std::string mMaxStr;
+ std::string mMinStr;
+ FontResource *mFont;
+ GUIText* mLabel;
+ int mLabelW;
+ COLOR mTextColor;
+ COLOR mLineColor;
+ COLOR mSliderColor;
+ bool mShowRange;
+ bool mShowCurr;
+ int mLineX;
+ int mLineY;
+ int mLineH;
+ int mLinePadding;
+ int mPadding;
+ int mSliderY;
+ int mSliderW;
+ int mSliderH;
+ bool mRendered;
+ int mFontHeight;
+ GUIAction *mAction;
+ bool mChangeOnDrag;
+ int mLineW;
+ bool mDragging;
+ ImageResource *mBackgroundImage;
+ ImageResource *mHandleImage;
+ ImageResource *mHandleHoverImage;
+};
+
+class MouseCursor : public RenderObject
+{
+public:
+ MouseCursor(int posX, int posY);
+ virtual ~MouseCursor();
+
+ virtual int Render(void);
+ virtual int Update(void);
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+ void Move(int deltaX, int deltaY);
+ void GetPos(int& x, int& y);
+ void LoadData(xml_node<>* node);
+ void ResetData(int resX, int resY);
+
+private:
+ int m_resX;
+ int m_resY;
+ bool m_moved;
+ float m_speedMultiplier;
+ COLOR m_color;
+ ImageResource *m_image;
+ bool m_present;
+};
+
+class GUIPatternPassword : public GUIObject, public RenderObject, public ActionObject
+{
+public:
+ GUIPatternPassword(xml_node<>* node);
+ virtual ~GUIPatternPassword();
+
+public:
+ virtual int Render(void);
+ virtual int Update(void);
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+ virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);
+
+protected:
+ void CalculateDotPositions();
+ void ResetActiveDots();
+ void ConnectDot(int dot_idx);
+ void ConnectIntermediateDots(int dot_idx);
+ int InDot(int x, int y);
+ bool DotUsed(int dot_idx);
+ static bool IsInRect(int x, int y, int rx, int ry, int rw, int rh);
+ void PatternDrawn();
+
+ struct Dot {
+ int x;
+ int y;
+ bool active;
+ };
+
+ Dot mDots[9];
+ int mConnectedDots[9];
+ size_t mConnectedDotsLen;
+ int mCurLineX;
+ int mCurLineY;
+ bool mTrackingTouch;
+ bool mNeedRender;
+
+ COLOR mDotColor;
+ COLOR mActiveDotColor;
+ COLOR mLineColor;
+ ImageResource *mDotImage;
+ ImageResource *mActiveDotImage;
+ gr_surface mDotCircle;
+ gr_surface mActiveDotCircle;
+ int mDotRadius;
+ int mLineWidth;
+
+ std::string mPassVar;
+ GUIAction *mAction;
+ int mUpdate;
+};
+
+
+// Helper APIs
+xml_node<>* FindNode(xml_node<>* parent, const char* nodename, int depth = 0);
+std::string LoadAttrString(xml_node<>* element, const char* attrname, const char* defaultvalue = "");
+int LoadAttrInt(xml_node<>* element, const char* attrname, int defaultvalue = 0);
+int LoadAttrIntScaleX(xml_node<>* element, const char* attrname, int defaultvalue = 0);
+int LoadAttrIntScaleY(xml_node<>* element, const char* attrname, int defaultvalue = 0);
+COLOR LoadAttrColor(xml_node<>* element, const char* attrname, bool* found_color, COLOR defaultvalue = COLOR(0,0,0,0));
+COLOR LoadAttrColor(xml_node<>* element, const char* attrname, COLOR defaultvalue = COLOR(0,0,0,0));
+FontResource* LoadAttrFont(xml_node<>* element, const char* attrname);
+ImageResource* LoadAttrImage(xml_node<>* element, const char* attrname);
+AnimationResource* LoadAttrAnimation(xml_node<>* element, const char* attrname);
+
+bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w = NULL, int* h = NULL, RenderObject::Placement* placement = NULL);
+
+#endif // _OBJECTS_HEADER
+
diff --git a/gui/pages.cpp b/gui/pages.cpp
new file mode 100644
index 000000000..4c98a7233
--- /dev/null
+++ b/gui/pages.cpp
@@ -0,0 +1,1470 @@
+/*
+ Copyright 2013 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+// pages.cpp - Source to manage GUI base objects
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "../twrp-functions.hpp"
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+#include "../minzip/SysUtil.h"
+#include "../minzip/Zip.h"
+#include "gui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "blanktimer.hpp"
+
+extern int gGuiRunning;
+
+std::map<std::string, PageSet*> PageManager::mPageSets;
+PageSet* PageManager::mCurrentSet;
+PageSet* PageManager::mBaseSet = NULL;
+MouseCursor *PageManager::mMouseCursor = NULL;
+HardwareKeyboard *PageManager::mHardwareKeyboard = NULL;
+
+int tw_x_offset = 0;
+int tw_y_offset = 0;
+
+// Helper routine to convert a string to a color declaration
+int ConvertStrToColor(std::string str, COLOR* color)
+{
+ // Set the default, solid black
+ memset(color, 0, sizeof(COLOR));
+ color->alpha = 255;
+
+ // Translate variables
+ DataManager::GetValue(str, str);
+
+ // Look for some defaults
+ if (str == "black") return 0;
+ else if (str == "white") { color->red = color->green = color->blue = 255; return 0; }
+ else if (str == "red") { color->red = 255; return 0; }
+ else if (str == "green") { color->green = 255; return 0; }
+ else if (str == "blue") { color->blue = 255; return 0; }
+
+ // At this point, we require an RGB(A) color
+ if (str[0] != '#')
+ return -1;
+
+ str.erase(0, 1);
+
+ int result;
+ if (str.size() >= 8) {
+ // We have alpha channel
+ string alpha = str.substr(6, 2);
+ result = strtol(alpha.c_str(), NULL, 16);
+ color->alpha = result & 0x000000FF;
+ str.resize(6);
+ result = strtol(str.c_str(), NULL, 16);
+ color->red = (result >> 16) & 0x000000FF;
+ color->green = (result >> 8) & 0x000000FF;
+ color->blue = result & 0x000000FF;
+ } else {
+ result = strtol(str.c_str(), NULL, 16);
+ color->red = (result >> 16) & 0x000000FF;
+ color->green = (result >> 8) & 0x000000FF;
+ color->blue = result & 0x000000FF;
+ }
+ return 0;
+}
+
+// Helper APIs
+xml_node<>* FindNode(xml_node<>* parent, const char* nodename, int depth /* = 0 */)
+{
+ if (!parent)
+ return NULL;
+
+ xml_node<>* child = parent->first_node(nodename);
+ if (child)
+ return child;
+
+ if (depth == 10) {
+ LOGERR("Too many style loops detected.\n");
+ return NULL;
+ }
+
+ xml_node<>* style = parent->first_node("style");
+ if (style) {
+ while (style) {
+ if (!style->first_attribute("name")) {
+ LOGERR("No name given for style.\n");
+ continue;
+ } else {
+ std::string name = style->first_attribute("name")->value();
+ xml_node<>* node = PageManager::FindStyle(name);
+
+ if (node) {
+ // We found the style that was named
+ xml_node<>* stylenode = FindNode(node, nodename, depth + 1);
+ if (stylenode)
+ return stylenode;
+ }
+ }
+ style = style->next_sibling("style");
+ }
+ } else {
+ // Search for stylename in the parent node <object type="foo" stylename="foo2">
+ xml_attribute<>* attr = parent->first_attribute("style");
+ // If no style is found anywhere else and the node wasn't found in the object itself
+ // as a special case we will search for a style that uses the same style name as the
+ // object type, so <object type="button"> would search for a style named "button"
+ if (!attr)
+ attr = parent->first_attribute("type");
+ if (attr) {
+ xml_node<>* node = PageManager::FindStyle(attr->value());
+ if (node) {
+ xml_node<>* stylenode = FindNode(node, nodename, depth + 1);
+ if (stylenode)
+ return stylenode;
+ }
+ }
+ }
+ return NULL;
+}
+
+std::string LoadAttrString(xml_node<>* element, const char* attrname, const char* defaultvalue)
+{
+ if (!element)
+ return defaultvalue;
+
+ xml_attribute<>* attr = element->first_attribute(attrname);
+ return attr ? attr->value() : defaultvalue;
+}
+
+int LoadAttrInt(xml_node<>* element, const char* attrname, int defaultvalue)
+{
+ string value = LoadAttrString(element, attrname);
+ // resolve variables
+ DataManager::GetValue(value, value);
+ return value.empty() ? defaultvalue : atoi(value.c_str());
+}
+
+int LoadAttrIntScaleX(xml_node<>* element, const char* attrname, int defaultvalue)
+{
+ return scale_theme_x(LoadAttrInt(element, attrname, defaultvalue));
+}
+
+int LoadAttrIntScaleY(xml_node<>* element, const char* attrname, int defaultvalue)
+{
+ return scale_theme_y(LoadAttrInt(element, attrname, defaultvalue));
+}
+
+COLOR LoadAttrColor(xml_node<>* element, const char* attrname, bool* found_color, COLOR defaultvalue)
+{
+ string value = LoadAttrString(element, attrname);
+ *found_color = !value.empty();
+ // resolve variables
+ DataManager::GetValue(value, value);
+ COLOR ret = defaultvalue;
+ if (ConvertStrToColor(value, &ret) == 0)
+ return ret;
+ else
+ return defaultvalue;
+}
+
+COLOR LoadAttrColor(xml_node<>* element, const char* attrname, COLOR defaultvalue)
+{
+ bool found_color = false;
+ return LoadAttrColor(element, attrname, &found_color, defaultvalue);
+}
+
+FontResource* LoadAttrFont(xml_node<>* element, const char* attrname)
+{
+ std::string name = LoadAttrString(element, attrname, "");
+ if (name.empty())
+ return NULL;
+ else
+ return PageManager::GetResources()->FindFont(name);
+}
+
+ImageResource* LoadAttrImage(xml_node<>* element, const char* attrname)
+{
+ std::string name = LoadAttrString(element, attrname, "");
+ if (name.empty())
+ return NULL;
+ else
+ return PageManager::GetResources()->FindImage(name);
+}
+
+AnimationResource* LoadAttrAnimation(xml_node<>* element, const char* attrname)
+{
+ std::string name = LoadAttrString(element, attrname, "");
+ if (name.empty())
+ return NULL;
+ else
+ return PageManager::GetResources()->FindAnimation(name);
+}
+
+bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w /* = NULL */, int* h /* = NULL */, RenderObject::Placement* placement /* = NULL */)
+{
+ if (!node)
+ return false;
+
+ if (node->first_attribute("x"))
+ *x = LoadAttrIntScaleX(node, "x") + tw_x_offset;
+
+ if (node->first_attribute("y"))
+ *y = LoadAttrIntScaleY(node, "y") + tw_y_offset;
+
+ if (w && node->first_attribute("w"))
+ *w = LoadAttrIntScaleX(node, "w");
+
+ if (h && node->first_attribute("h"))
+ *h = LoadAttrIntScaleY(node, "h");
+
+ if (placement && node->first_attribute("placement"))
+ *placement = (RenderObject::Placement) LoadAttrInt(node, "placement");
+
+ return true;
+}
+
+int ActionObject::SetActionPos(int x, int y, int w, int h)
+{
+ if (x < 0 || y < 0)
+ return -1;
+
+ mActionX = x;
+ mActionY = y;
+ if (w || h)
+ {
+ mActionW = w;
+ mActionH = h;
+ }
+ return 0;
+}
+
+Page::Page(xml_node<>* page, std::vector<xml_node<>*> *templates)
+{
+ mTouchStart = NULL;
+
+ // We can memset the whole structure, because the alpha channel is ignored
+ memset(&mBackground, 0, sizeof(COLOR));
+
+ // With NULL, we make a console-only display
+ if (!page)
+ {
+ mName = "console";
+
+ GUIConsole* element = new GUIConsole(NULL);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ return;
+ }
+
+ if (page->first_attribute("name"))
+ mName = page->first_attribute("name")->value();
+ else
+ {
+ LOGERR("No page name attribute found!\n");
+ return;
+ }
+
+ LOGINFO("Loading page %s\n", mName.c_str());
+
+ // This is a recursive routine for template handling
+ ProcessNode(page, templates, 0);
+}
+
+Page::~Page()
+{
+ for (std::vector<GUIObject*>::iterator itr = mObjects.begin(); itr != mObjects.end(); ++itr)
+ delete *itr;
+}
+
+bool Page::ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates, int depth)
+{
+ if (depth == 10)
+ {
+ LOGERR("Page processing depth has exceeded 10. Failing out. This is likely a recursive template.\n");
+ return false;
+ }
+
+ for (xml_node<>* child = page->first_node(); child; child = child->next_sibling())
+ {
+ std::string type = child->name();
+
+ if (type == "background") {
+ mBackground = LoadAttrColor(child, "color", COLOR(0,0,0,0));
+ continue;
+ }
+
+ if (type == "object") {
+ // legacy format : <object type="...">
+ xml_attribute<>* attr = child->first_attribute("type");
+ type = attr ? attr->value() : "*unspecified*";
+ }
+
+ if (type == "text")
+ {
+ GUIText* element = new GUIText(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "image")
+ {
+ GUIImage* element = new GUIImage(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ }
+ else if (type == "fill")
+ {
+ GUIFill* element = new GUIFill(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ }
+ else if (type == "action")
+ {
+ GUIAction* element = new GUIAction(child);
+ mObjects.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "console")
+ {
+ GUIConsole* element = new GUIConsole(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "button")
+ {
+ GUIButton* element = new GUIButton(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "checkbox")
+ {
+ GUICheckbox* element = new GUICheckbox(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "fileselector")
+ {
+ GUIFileSelector* element = new GUIFileSelector(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "animation")
+ {
+ GUIAnimation* element = new GUIAnimation(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ }
+ else if (type == "progressbar")
+ {
+ GUIProgressBar* element = new GUIProgressBar(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "slider")
+ {
+ GUISlider* element = new GUISlider(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "slidervalue")
+ {
+ GUISliderValue *element = new GUISliderValue(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "listbox")
+ {
+ GUIListBox* element = new GUIListBox(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "keyboard")
+ {
+ GUIKeyboard* element = new GUIKeyboard(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "input")
+ {
+ GUIInput* element = new GUIInput(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ mInputs.push_back(element);
+ }
+ else if (type == "partitionlist")
+ {
+ GUIPartitionList* element = new GUIPartitionList(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "patternpassword")
+ {
+ GUIPatternPassword* element = new GUIPatternPassword(child);
+ mObjects.push_back(element);
+ mRenders.push_back(element);
+ mActions.push_back(element);
+ }
+ else if (type == "template")
+ {
+ if (!templates || !child->first_attribute("name"))
+ {
+ LOGERR("Invalid template request.\n");
+ }
+ else
+ {
+ std::string name = child->first_attribute("name")->value();
+ xml_node<>* node;
+ bool node_found = false;
+
+ // We need to find the correct template
+ for (std::vector<xml_node<>*>::iterator itr = templates->begin(); itr != templates->end(); itr++) {
+ node = (*itr)->first_node("template");
+
+ while (node)
+ {
+ if (!node->first_attribute("name"))
+ continue;
+
+ if (name == node->first_attribute("name")->value())
+ {
+ if (!ProcessNode(node, templates, depth + 1))
+ return false;
+ else {
+ node_found = true;
+ break;
+ }
+ }
+ if (node_found)
+ break;
+ node = node->next_sibling("template");
+ }
+ // [check] why is there no if (node_found) here too?
+ }
+ }
+ }
+ else
+ {
+ LOGERR("Unknown object type: %s.\n", type.c_str());
+ }
+ }
+ return true;
+}
+
+int Page::Render(void)
+{
+ // Render background
+ gr_color(mBackground.red, mBackground.green, mBackground.blue, mBackground.alpha);
+ gr_fill(0, 0, gr_fb_width(), gr_fb_height());
+
+ // Render remaining objects
+ std::vector<RenderObject*>::iterator iter;
+ for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
+ {
+ if ((*iter)->Render())
+ LOGERR("A render request has failed.\n");
+ }
+ return 0;
+}
+
+int Page::Update(void)
+{
+ int retCode = 0;
+
+ std::vector<RenderObject*>::iterator iter;
+ for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
+ {
+ int ret = (*iter)->Update();
+ if (ret < 0)
+ LOGERR("An update request has failed.\n");
+ else if (ret > retCode)
+ retCode = ret;
+ }
+
+ return retCode;
+}
+
+int Page::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ // By default, return 1 to ignore further touches if nobody is listening
+ int ret = 1;
+
+ // Don't try to handle a lack of handlers
+ if (mActions.size() == 0)
+ return ret;
+
+ // We record mTouchStart so we can pass all the touch stream to the same handler
+ if (state == TOUCH_START)
+ {
+ std::vector<ActionObject*>::reverse_iterator iter;
+ // We work backwards, from top-most element to bottom-most element
+ for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
+ {
+ if ((*iter)->IsInRegion(x, y))
+ {
+ mTouchStart = (*iter);
+ ret = mTouchStart->NotifyTouch(state, x, y);
+ if (ret >= 0)
+ break;
+ mTouchStart = NULL;
+ }
+ }
+ }
+ else if (state == TOUCH_RELEASE && mTouchStart != NULL)
+ {
+ ret = mTouchStart->NotifyTouch(state, x, y);
+ mTouchStart = NULL;
+ }
+ else if ((state == TOUCH_DRAG || state == TOUCH_HOLD || state == TOUCH_REPEAT) && mTouchStart != NULL)
+ {
+ ret = mTouchStart->NotifyTouch(state, x, y);
+ }
+ return ret;
+}
+
+int Page::NotifyKey(int key, bool down)
+{
+ std::vector<ActionObject*>::reverse_iterator iter;
+
+ // Don't try to handle a lack of handlers
+ if (mActions.size() == 0)
+ return 1;
+
+ int ret = 1;
+ // We work backwards, from top-most element to bottom-most element
+ for (iter = mActions.rbegin(); iter != mActions.rend(); iter++)
+ {
+ ret = (*iter)->NotifyKey(key, down);
+ if (ret < 0) {
+ LOGERR("An action handler has returned an error\n");
+ ret = 1;
+ }
+ }
+ return ret;
+}
+
+int Page::NotifyKeyboard(int key)
+{
+ std::vector<InputObject*>::reverse_iterator iter;
+
+ // Don't try to handle a lack of handlers
+ if (mInputs.size() == 0)
+ return 1;
+
+ // We work backwards, from top-most element to bottom-most element
+ for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
+ {
+ int ret = (*iter)->NotifyKeyboard(key);
+ if (ret == 0)
+ return 0;
+ else if (ret < 0)
+ LOGERR("A keyboard handler has returned an error");
+ }
+ return 1;
+}
+
+int Page::SetKeyBoardFocus(int inFocus)
+{
+ std::vector<InputObject*>::reverse_iterator iter;
+
+ // Don't try to handle a lack of handlers
+ if (mInputs.size() == 0)
+ return 1;
+
+ // We work backwards, from top-most element to bottom-most element
+ for (iter = mInputs.rbegin(); iter != mInputs.rend(); iter++)
+ {
+ int ret = (*iter)->SetInputFocus(inFocus);
+ if (ret == 0)
+ return 0;
+ else if (ret < 0)
+ LOGERR("An input focus handler has returned an error");
+ }
+ return 1;
+}
+
+void Page::SetPageFocus(int inFocus)
+{
+ // Render remaining objects
+ std::vector<RenderObject*>::iterator iter;
+ for (iter = mRenders.begin(); iter != mRenders.end(); iter++)
+ (*iter)->SetPageFocus(inFocus);
+
+ return;
+}
+
+int Page::NotifyVarChange(std::string varName, std::string value)
+{
+ std::vector<GUIObject*>::iterator iter;
+ for (iter = mObjects.begin(); iter != mObjects.end(); ++iter)
+ {
+ if ((*iter)->NotifyVarChange(varName, value))
+ LOGERR("An action handler errored on NotifyVarChange.\n");
+ }
+ return 0;
+}
+
+PageSet::PageSet(char* xmlFile)
+{
+ mResources = new ResourceManager;
+ mCurrentPage = NULL;
+
+ mXmlFile = xmlFile;
+ if (xmlFile)
+ mDoc.parse<0>(mXmlFile);
+ else
+ mCurrentPage = new Page(NULL, NULL);
+}
+
+PageSet::~PageSet()
+{
+ mOverlays.clear();
+ for (std::vector<Page*>::iterator itr = mPages.begin(); itr != mPages.end(); ++itr)
+ delete *itr;
+
+ delete mResources;
+ free(mXmlFile);
+
+ mDoc.clear();
+
+ for (std::vector<xml_document<>*>::iterator itr = mIncludedDocs.begin(); itr != mIncludedDocs.end(); ++itr) {
+ (*itr)->clear();
+ delete *itr;
+ }
+}
+
+int PageSet::Load(ZipArchive* package)
+{
+ xml_node<>* parent;
+ xml_node<>* child;
+ xml_node<>* xmltemplate;
+ xml_node<>* xmlstyle;
+
+ parent = mDoc.first_node("recovery");
+ if (!parent)
+ parent = mDoc.first_node("install");
+
+ set_scale_values(1, 1); // Reset any previous scaling values
+
+ // Now, let's parse the XML
+ LOGINFO("Checking resolution...\n");
+ child = parent->first_node("details");
+ if (child) {
+ xml_node<>* resolution = child->first_node("resolution");
+ if (resolution) {
+ xml_attribute<>* width_attr = resolution->first_attribute("width");
+ xml_attribute<>* height_attr = resolution->first_attribute("height");
+ xml_attribute<>* noscale_attr = resolution->first_attribute("noscaling");
+ if (width_attr && height_attr && !noscale_attr) {
+ int width = atoi(width_attr->value());
+ int height = atoi(height_attr->value());
+ int offx = 0, offy = 0;
+#ifdef TW_ROUND_SCREEN
+ xml_node<>* roundscreen = child->first_node("roundscreen");
+ if (roundscreen) {
+ LOGINFO("TW_ROUND_SCREEN := true, using round screen XML settings.\n");
+ xml_attribute<>* offx_attr = roundscreen->first_attribute("offset_x");
+ xml_attribute<>* offy_attr = roundscreen->first_attribute("offset_y");
+ if (offx_attr) {
+ offx = atoi(offx_attr->value());
+ }
+ if (offy_attr) {
+ offy = atoi(offy_attr->value());
+ }
+ }
+#endif
+ if (width != 0 && height != 0) {
+ float scale_w = ((float)gr_fb_width() - ((float)offx * 2.0)) / (float)width;
+ float scale_h = ((float)gr_fb_height() - ((float)offy * 2.0)) / (float)height;
+#ifdef TW_ROUND_SCREEN
+ float scale_off_w = (float)gr_fb_width() / (float)width;
+ float scale_off_h = (float)gr_fb_height() / (float)height;
+ tw_x_offset = offx * scale_off_w;
+ tw_y_offset = offy * scale_off_h;
+#endif
+ if (scale_w != 1 || scale_h != 1) {
+ LOGINFO("Scaling theme width %fx and height %fx, offsets x: %i y: %i\n", scale_w, scale_h, tw_x_offset, tw_y_offset);
+ set_scale_values(scale_w, scale_h);
+ }
+ }
+ } else {
+ LOGINFO("XML does not contain width and height, no scaling will be applied\n");
+ }
+ } else {
+ LOGINFO("XML contains no resolution tag, no scaling will be applied.\n");
+ }
+ } else {
+ LOGINFO("XML contains no details tag, no scaling will be applied.\n");
+ }
+ LOGINFO("Loading resources...\n");
+ child = parent->first_node("resources");
+ if (child)
+ mResources->LoadResources(child, package);
+
+ LOGINFO("Loading variables...\n");
+ child = parent->first_node("variables");
+ if (child)
+ LoadVariables(child);
+
+ LOGINFO("Loading mouse cursor...\n");
+ child = parent->first_node("mousecursor");
+ if(child)
+ PageManager::LoadCursorData(child);
+
+ LOGINFO("Loading pages...\n");
+ // This may be NULL if no templates are present
+ xmltemplate = parent->first_node("templates");
+ if (xmltemplate)
+ templates.push_back(xmltemplate);
+
+ // Load styles if present
+ xmlstyle = parent->first_node("styles");
+ if (xmlstyle)
+ styles.push_back(xmlstyle);
+
+ child = parent->first_node("pages");
+ if (child) {
+ if (LoadPages(child)) {
+ LOGERR("PageSet::Load returning -1\n");
+ return -1;
+ }
+ }
+
+ return CheckInclude(package, &mDoc);
+}
+
+int PageSet::CheckInclude(ZipArchive* package, xml_document<> *parentDoc)
+{
+ xml_node<>* par;
+ xml_node<>* par2;
+ xml_node<>* chld;
+ xml_node<>* parent;
+ xml_node<>* child;
+ xml_node<>* xmltemplate;
+ xml_node<>* xmlstyle;
+ long len;
+ char* xmlFile = NULL;
+ string filename;
+ xml_document<> *doc = NULL;
+
+ par = parentDoc->first_node("recovery");
+ if (!par) {
+ par = parentDoc->first_node("install");
+ }
+ if (!par) {
+ return 0;
+ }
+
+ par2 = par->first_node("include");
+ if (!par2)
+ return 0;
+ chld = par2->first_node("xmlfile");
+ while (chld != NULL) {
+ xml_attribute<>* attr = chld->first_attribute("name");
+ if (!attr)
+ break;
+
+ if (!package) {
+ // We can try to load the XML directly...
+ filename = TWRES;
+ filename += attr->value();
+ LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
+ struct stat st;
+ if(stat(filename.c_str(),&st) != 0) {
+ LOGERR("Unable to locate '%s'\n", filename.c_str());
+ return -1;
+ }
+
+ len = st.st_size;
+ xmlFile = (char*) malloc(len + 1);
+ if (!xmlFile)
+ return -1;
+
+ int fd = open(filename.c_str(), O_RDONLY);
+ if (fd == -1)
+ return -1;
+
+ read(fd, xmlFile, len);
+ close(fd);
+ } else {
+ filename += attr->value();
+ LOGINFO("PageSet::CheckInclude loading filename: '%s'\n", filename.c_str());
+ const ZipEntry* ui_xml = mzFindZipEntry(package, filename.c_str());
+ if (ui_xml == NULL)
+ {
+ LOGERR("Unable to locate '%s' in zip file\n", filename.c_str());
+ return -1;
+ }
+
+ // Allocate the buffer for the file
+ len = mzGetZipEntryUncompLen(ui_xml);
+ xmlFile = (char*) malloc(len + 1);
+ if (!xmlFile)
+ return -1;
+
+ if (!mzExtractZipEntryToBuffer(package, ui_xml, (unsigned char*) xmlFile))
+ {
+ LOGERR("Unable to extract '%s'\n", filename.c_str());
+ return -1;
+ }
+ }
+
+ xmlFile[len] = '\0';
+ doc = new xml_document<>();
+ doc->parse<0>(xmlFile);
+
+ parent = doc->first_node("recovery");
+ if (!parent)
+ parent = doc->first_node("install");
+
+ // Now, let's parse the XML
+ LOGINFO("Loading included resources...\n");
+ child = parent->first_node("resources");
+ if (child)
+ mResources->LoadResources(child, package);
+
+ LOGINFO("Loading included variables...\n");
+ child = parent->first_node("variables");
+ if (child)
+ LoadVariables(child);
+
+ LOGINFO("Loading mouse cursor...\n");
+ child = parent->first_node("mousecursor");
+ if(child)
+ PageManager::LoadCursorData(child);
+
+ LOGINFO("Loading included pages...\n");
+ // This may be NULL if no templates are present
+ xmltemplate = parent->first_node("templates");
+ if (xmltemplate)
+ templates.push_back(xmltemplate);
+
+ // Load styles if present
+ xmlstyle = parent->first_node("styles");
+ if (xmlstyle)
+ styles.push_back(xmlstyle);
+
+ child = parent->first_node("pages");
+ if (child && LoadPages(child))
+ {
+ templates.pop_back();
+ doc->clear();
+ delete doc;
+ return -1;
+ }
+
+ mIncludedDocs.push_back(doc);
+
+ if (CheckInclude(package, doc))
+ return -1;
+
+ chld = chld->next_sibling("xmlfile");
+ }
+
+ return 0;
+}
+
+int PageSet::SetPage(std::string page)
+{
+ Page* tmp = FindPage(page);
+ if (tmp)
+ {
+ if (mCurrentPage) mCurrentPage->SetPageFocus(0);
+ mCurrentPage = tmp;
+ mCurrentPage->SetPageFocus(1);
+ mCurrentPage->NotifyVarChange("", "");
+ return 0;
+ }
+ else
+ {
+ LOGERR("Unable to locate page (%s)\n", page.c_str());
+ }
+ return -1;
+}
+
+int PageSet::SetOverlay(Page* page)
+{
+ if (page) {
+ if (mOverlays.size() >= 10) {
+ LOGERR("Too many overlays requested, max is 10.\n");
+ return -1;
+ }
+
+ std::vector<Page*>::iterator iter;
+ for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
+ if ((*iter)->GetName() == page->GetName()) {
+ mOverlays.erase(iter);
+ // SetOverlay() is (and should stay) the only function which
+ // adds to mOverlays. Then, each page can appear at most once.
+ break;
+ }
+ }
+
+ page->SetPageFocus(1);
+ page->NotifyVarChange("", "");
+
+ if (!mOverlays.empty())
+ mOverlays.back()->SetPageFocus(0);
+
+ mOverlays.push_back(page);
+ } else {
+ if (!mOverlays.empty()) {
+ mOverlays.back()->SetPageFocus(0);
+ mOverlays.pop_back();
+ if (!mOverlays.empty())
+ mOverlays.back()->SetPageFocus(1);
+ else if (mCurrentPage)
+ mCurrentPage->SetPageFocus(1); // Just in case somehow the regular page lost focus, we'll set it again
+ }
+ }
+ return 0;
+}
+
+const ResourceManager* PageSet::GetResources()
+{
+ return mResources;
+}
+
+Page* PageSet::FindPage(std::string name)
+{
+ std::vector<Page*>::iterator iter;
+
+ for (iter = mPages.begin(); iter != mPages.end(); iter++)
+ {
+ if (name == (*iter)->GetName())
+ return (*iter);
+ }
+ return NULL;
+}
+
+int PageSet::LoadVariables(xml_node<>* vars)
+{
+ xml_node<>* child;
+ xml_attribute<> *name, *value, *persist;
+ int p;
+
+ child = vars->first_node("variable");
+ while (child)
+ {
+ name = child->first_attribute("name");
+ value = child->first_attribute("value");
+ persist = child->first_attribute("persist");
+ if(name && value)
+ {
+ if (strcmp(name->value(), "tw_x_offset") == 0) {
+ tw_x_offset = atoi(value->value());
+ child = child->next_sibling("variable");
+ continue;
+ }
+ if (strcmp(name->value(), "tw_y_offset") == 0) {
+ tw_y_offset = atoi(value->value());
+ child = child->next_sibling("variable");
+ continue;
+ }
+ p = persist ? atoi(persist->value()) : 0;
+ string temp = value->value();
+ string valstr = gui_parse_text(temp);
+
+ if (valstr.find("+") != string::npos) {
+ string val1str = valstr;
+ val1str = val1str.substr(0, val1str.find('+'));
+ string val2str = valstr;
+ val2str = val2str.substr(val2str.find('+') + 1, string::npos);
+ int val1 = atoi(val1str.c_str());
+ int val2 = atoi(val2str.c_str());
+ int val = val1 + val2;
+
+ DataManager::SetValue(name->value(), val, p);
+ } else if (valstr.find("-") != string::npos) {
+ string val1str = valstr;
+ val1str = val1str.substr(0, val1str.find('-'));
+ string val2str = valstr;
+ val2str = val2str.substr(val2str.find('-') + 1, string::npos);
+ int val1 = atoi(val1str.c_str());
+ int val2 = atoi(val2str.c_str());
+ int val = val1 - val2;
+
+ DataManager::SetValue(name->value(), val, p);
+ } else {
+ DataManager::SetValue(name->value(), valstr, p);
+ }
+ }
+
+ child = child->next_sibling("variable");
+ }
+ return 0;
+}
+
+int PageSet::LoadPages(xml_node<>* pages)
+{
+ xml_node<>* child;
+
+ if (!pages)
+ return -1;
+
+ child = pages->first_node("page");
+ while (child != NULL)
+ {
+ Page* page = new Page(child, &templates);
+ if (page->GetName().empty())
+ {
+ LOGERR("Unable to process load page\n");
+ delete page;
+ }
+ else
+ {
+ mPages.push_back(page);
+ }
+ child = child->next_sibling("page");
+ }
+ if (mPages.size() > 0)
+ return 0;
+ return -1;
+}
+
+int PageSet::IsCurrentPage(Page* page)
+{
+ return ((mCurrentPage && mCurrentPage == page) ? 1 : 0);
+}
+
+int PageSet::Render(void)
+{
+ int ret;
+
+ ret = (mCurrentPage ? mCurrentPage->Render() : -1);
+ if (ret < 0)
+ return ret;
+
+ std::vector<Page*>::iterator iter;
+
+ for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
+ ret = ((*iter) ? (*iter)->Render() : -1);
+ if (ret < 0)
+ return ret;
+ }
+ return ret;
+}
+
+int PageSet::Update(void)
+{
+ int ret;
+
+ ret = (mCurrentPage ? mCurrentPage->Update() : -1);
+ if (ret < 0 || ret > 1)
+ return ret;
+
+ std::vector<Page*>::iterator iter;
+
+ for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++) {
+ ret = ((*iter) ? (*iter)->Update() : -1);
+ if (ret < 0)
+ return ret;
+ }
+ return ret;
+}
+
+int PageSet::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if (!mOverlays.empty())
+ return mOverlays.back()->NotifyTouch(state, x, y);
+
+ return (mCurrentPage ? mCurrentPage->NotifyTouch(state, x, y) : -1);
+}
+
+int PageSet::NotifyKey(int key, bool down)
+{
+ if (!mOverlays.empty())
+ return mOverlays.back()->NotifyKey(key, down);
+
+ return (mCurrentPage ? mCurrentPage->NotifyKey(key, down) : -1);
+}
+
+int PageSet::NotifyKeyboard(int key)
+{
+ if (!mOverlays.empty())
+ return mOverlays.back()->NotifyKeyboard(key);
+
+ return (mCurrentPage ? mCurrentPage->NotifyKeyboard(key) : -1);
+}
+
+int PageSet::SetKeyBoardFocus(int inFocus)
+{
+ if (!mOverlays.empty())
+ return mOverlays.back()->SetKeyBoardFocus(inFocus);
+
+ return (mCurrentPage ? mCurrentPage->SetKeyBoardFocus(inFocus) : -1);
+}
+
+int PageSet::NotifyVarChange(std::string varName, std::string value)
+{
+ std::vector<Page*>::iterator iter;
+
+ for (iter = mOverlays.begin(); iter != mOverlays.end(); iter++)
+ (*iter)->NotifyVarChange(varName, value);
+
+ return (mCurrentPage ? mCurrentPage->NotifyVarChange(varName, value) : -1);
+}
+
+int PageManager::LoadPackage(std::string name, std::string package, std::string startpage)
+{
+ int fd;
+ ZipArchive zip, *pZip = NULL;
+ long len;
+ char* xmlFile = NULL;
+ PageSet* pageSet = NULL;
+ int ret;
+ MemMapping map;
+
+ // Open the XML file
+ LOGINFO("Loading package: %s (%s)\n", name.c_str(), package.c_str());
+ if (package.size() > 4 && package.substr(package.size() - 4) != ".zip")
+ {
+ LOGINFO("Load XML directly\n");
+ tw_x_offset = TW_X_OFFSET;
+ tw_y_offset = TW_Y_OFFSET;
+ // We can try to load the XML directly...
+ struct stat st;
+ if(stat(package.c_str(),&st) != 0)
+ return -1;
+
+ len = st.st_size;
+ xmlFile = (char*) malloc(len + 1);
+ if (!xmlFile)
+ return -1;
+
+ fd = open(package.c_str(), O_RDONLY);
+ if (fd == -1)
+ goto error;
+
+ read(fd, xmlFile, len);
+ close(fd);
+ }
+ else
+ {
+ LOGINFO("Loading zip theme\n");
+ tw_x_offset = 0;
+ tw_y_offset = 0;
+ if (!TWFunc::Path_Exists(package))
+ return -1;
+ if (sysMapFile(package.c_str(), &map) != 0) {
+ LOGERR("Failed to map '%s'\n", package.c_str());
+ return -1;
+ }
+ if (mzOpenZipArchive(map.addr, map.length, &zip)) {
+ LOGERR("Unable to open zip archive '%s'\n", package.c_str());
+ sysReleaseMap(&map);
+ return -1;
+ }
+ pZip = &zip;
+ const ZipEntry* ui_xml = mzFindZipEntry(&zip, "ui.xml");
+ if (ui_xml == NULL)
+ {
+ LOGERR("Unable to locate ui.xml in zip file\n");
+ goto error;
+ }
+
+ // Allocate the buffer for the file
+ len = mzGetZipEntryUncompLen(ui_xml);
+ xmlFile = (char*) malloc(len + 1);
+ if (!xmlFile)
+ goto error;
+
+ if (!mzExtractZipEntryToBuffer(&zip, ui_xml, (unsigned char*) xmlFile))
+ {
+ LOGERR("Unable to extract ui.xml\n");
+ goto error;
+ }
+ }
+
+ // NULL-terminate the string
+ xmlFile[len] = 0x00;
+
+ // Before loading, mCurrentSet must be the loading package so we can find resources
+ pageSet = mCurrentSet;
+ mCurrentSet = new PageSet(xmlFile);
+
+ ret = mCurrentSet->Load(pZip);
+ if (ret == 0)
+ {
+ mCurrentSet->SetPage(startpage);
+ mPageSets.insert(std::pair<std::string, PageSet*>(name, mCurrentSet));
+ }
+ else
+ {
+ LOGERR("Package %s failed to load.\n", name.c_str());
+ }
+
+ // The first successful package we loaded is the base
+ if (mBaseSet == NULL)
+ mBaseSet = mCurrentSet;
+
+ mCurrentSet = pageSet;
+
+ if (pZip) {
+ mzCloseZipArchive(pZip);
+ sysReleaseMap(&map);
+ }
+ return ret;
+
+error:
+ LOGERR("An internal error has occurred.\n");
+ if (pZip) {
+ mzCloseZipArchive(pZip);
+ sysReleaseMap(&map);
+ }
+ if (xmlFile)
+ free(xmlFile);
+ return -1;
+}
+
+PageSet* PageManager::FindPackage(std::string name)
+{
+ std::map<std::string, PageSet*>::iterator iter;
+
+ iter = mPageSets.find(name);
+ if (iter != mPageSets.end())
+ return (*iter).second;
+
+ LOGERR("Unable to locate package %s\n", name.c_str());
+ return NULL;
+}
+
+PageSet* PageManager::SelectPackage(std::string name)
+{
+ LOGINFO("Switching packages (%s)\n", name.c_str());
+ PageSet* tmp;
+
+ tmp = FindPackage(name);
+ if (tmp)
+ {
+ mCurrentSet = tmp;
+ mCurrentSet->NotifyVarChange("", "");
+ }
+ else
+ LOGERR("Unable to find package.\n");
+
+ return mCurrentSet;
+}
+
+int PageManager::ReloadPackage(std::string name, std::string package)
+{
+ std::map<std::string, PageSet*>::iterator iter;
+
+ iter = mPageSets.find(name);
+ if (iter == mPageSets.end())
+ return -1;
+
+ if(mMouseCursor)
+ mMouseCursor->ResetData(gr_fb_width(), gr_fb_height());
+
+ PageSet* set = (*iter).second;
+ mPageSets.erase(iter);
+
+ if (LoadPackage(name, package, "main") != 0)
+ {
+ LOGERR("Failed to load package '%s'.\n", package.c_str());
+ mPageSets.insert(std::pair<std::string, PageSet*>(name, set));
+ return -1;
+ }
+ if (mCurrentSet == set)
+ SelectPackage(name);
+ if (mBaseSet == set)
+ mBaseSet = mCurrentSet;
+ delete set;
+ return 0;
+}
+
+void PageManager::ReleasePackage(std::string name)
+{
+ std::map<std::string, PageSet*>::iterator iter;
+
+ iter = mPageSets.find(name);
+ if (iter == mPageSets.end())
+ return;
+
+ PageSet* set = (*iter).second;
+ mPageSets.erase(iter);
+ delete set;
+ return;
+}
+
+int PageManager::ChangePage(std::string name)
+{
+ DataManager::SetValue("tw_operation_state", 0);
+ int ret = (mCurrentSet ? mCurrentSet->SetPage(name) : -1);
+ return ret;
+}
+
+int PageManager::ChangeOverlay(std::string name)
+{
+ if (name.empty())
+ return mCurrentSet->SetOverlay(NULL);
+ else
+ {
+ Page* page = mBaseSet ? mBaseSet->FindPage(name) : NULL;
+ return mCurrentSet->SetOverlay(page);
+ }
+}
+
+const ResourceManager* PageManager::GetResources()
+{
+ return (mCurrentSet ? mCurrentSet->GetResources() : NULL);
+}
+
+int PageManager::SwitchToConsole(void)
+{
+ PageSet* console = new PageSet(NULL);
+
+ mCurrentSet = console;
+ return 0;
+}
+
+int PageManager::EndConsole(void)
+{
+ if (mCurrentSet && mBaseSet) {
+ delete mCurrentSet;
+ mCurrentSet = mBaseSet;
+ return 0;
+ }
+ return -1;
+}
+
+int PageManager::IsCurrentPage(Page* page)
+{
+ return (mCurrentSet ? mCurrentSet->IsCurrentPage(page) : 0);
+}
+
+int PageManager::Render(void)
+{
+ int res = (mCurrentSet ? mCurrentSet->Render() : -1);
+ if(mMouseCursor)
+ mMouseCursor->Render();
+ return res;
+}
+
+HardwareKeyboard *PageManager::GetHardwareKeyboard()
+{
+ if(!mHardwareKeyboard)
+ mHardwareKeyboard = new HardwareKeyboard();
+ return mHardwareKeyboard;
+}
+
+xml_node<>* PageManager::FindStyle(std::string name)
+{
+ for (std::vector<xml_node<>*>::iterator itr = mCurrentSet->styles.begin(); itr != mCurrentSet->styles.end(); itr++) {
+ xml_node<>* node = (*itr)->first_node("style");
+
+ while (node) {
+ if (!node->first_attribute("name"))
+ continue;
+
+ if (name == node->first_attribute("name")->value())
+ return node;
+ node = node->next_sibling("style");
+ }
+ }
+ return NULL;
+}
+
+MouseCursor *PageManager::GetMouseCursor()
+{
+ if(!mMouseCursor)
+ mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
+ return mMouseCursor;
+}
+
+void PageManager::LoadCursorData(xml_node<>* node)
+{
+ if(!mMouseCursor)
+ mMouseCursor = new MouseCursor(gr_fb_width(), gr_fb_height());
+
+ mMouseCursor->LoadData(node);
+}
+
+int PageManager::Update(void)
+{
+ if(blankTimer.isScreenOff())
+ return 0;
+
+ int res = (mCurrentSet ? mCurrentSet->Update() : -1);
+
+ if(mMouseCursor)
+ {
+ int c_res = mMouseCursor->Update();
+ if(c_res > res)
+ res = c_res;
+ }
+ return res;
+}
+
+int PageManager::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ return (mCurrentSet ? mCurrentSet->NotifyTouch(state, x, y) : -1);
+}
+
+int PageManager::NotifyKey(int key, bool down)
+{
+ return (mCurrentSet ? mCurrentSet->NotifyKey(key, down) : -1);
+}
+
+int PageManager::NotifyKeyboard(int key)
+{
+ return (mCurrentSet ? mCurrentSet->NotifyKeyboard(key) : -1);
+}
+
+int PageManager::SetKeyBoardFocus(int inFocus)
+{
+ return (mCurrentSet ? mCurrentSet->SetKeyBoardFocus(inFocus) : -1);
+}
+
+int PageManager::NotifyVarChange(std::string varName, std::string value)
+{
+ return (mCurrentSet ? mCurrentSet->NotifyVarChange(varName, value) : -1);
+}
+
+extern "C" void gui_notifyVarChange(const char *name, const char* value)
+{
+ if (!gGuiRunning)
+ return;
+
+ PageManager::NotifyVarChange(name, value);
+}
diff --git a/gui/pages.h b/gui/pages.h
new file mode 100644
index 000000000..d407162a2
--- /dev/null
+++ b/gui/pages.h
@@ -0,0 +1,7 @@
+#ifndef _PAGES_HEADER
+#define _PAGES_HEADER
+
+void gui_notifyVarChange(const char *name, const char* value);
+
+#endif // _PAGES_HEADER
+
diff --git a/gui/pages.hpp b/gui/pages.hpp
new file mode 100644
index 000000000..81112f979
--- /dev/null
+++ b/gui/pages.hpp
@@ -0,0 +1,170 @@
+// pages.hpp - Base classes for page manager of GUI
+
+#ifndef _PAGES_HEADER_HPP
+#define _PAGES_HEADER_HPP
+
+#include "../minzip/Zip.h"
+#include <vector>
+#include <map>
+#include "rapidxml.hpp"
+using namespace rapidxml;
+
+enum TOUCH_STATE {
+ TOUCH_START = 0,
+ TOUCH_DRAG = 1,
+ TOUCH_RELEASE = 2,
+ TOUCH_HOLD = 3,
+ TOUCH_REPEAT = 4
+};
+
+struct COLOR {
+ unsigned char red;
+ unsigned char green;
+ unsigned char blue;
+ unsigned char alpha;
+ COLOR() : red(0), green(0), blue(0), alpha(0) {}
+ COLOR(unsigned char r, unsigned char g, unsigned char b, unsigned char a = 255)
+ : red(r), green(g), blue(b), alpha(a) {}
+};
+
+// Utility Functions
+int ConvertStrToColor(std::string str, COLOR* color);
+int gui_forceRender(void);
+int gui_changePage(std::string newPage);
+int gui_changeOverlay(std::string newPage);
+std::string gui_parse_text(string inText);
+
+class Resource;
+class ResourceManager;
+class RenderObject;
+class ActionObject;
+class InputObject;
+class MouseCursor;
+class GUIObject;
+class HardwareKeyboard;
+
+class Page
+{
+public:
+ Page(xml_node<>* page, std::vector<xml_node<>*> *templates);
+ virtual ~Page();
+
+ std::string GetName(void) { return mName; }
+
+public:
+ virtual int Render(void);
+ virtual int Update(void);
+ virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
+ virtual int NotifyKey(int key, bool down);
+ virtual int NotifyKeyboard(int key);
+ virtual int SetKeyBoardFocus(int inFocus);
+ virtual int NotifyVarChange(std::string varName, std::string value);
+ virtual void SetPageFocus(int inFocus);
+
+protected:
+ std::string mName;
+ std::vector<GUIObject*> mObjects;
+ std::vector<RenderObject*> mRenders;
+ std::vector<ActionObject*> mActions;
+ std::vector<InputObject*> mInputs;
+
+ ActionObject* mTouchStart;
+ COLOR mBackground;
+
+protected:
+ bool ProcessNode(xml_node<>* page, std::vector<xml_node<>*> *templates, int depth);
+};
+
+class PageSet
+{
+public:
+ PageSet(char* xmlFile);
+ virtual ~PageSet();
+
+public:
+ int Load(ZipArchive* package);
+ int CheckInclude(ZipArchive* package, xml_document<> *parentDoc);
+
+ Page* FindPage(std::string name);
+ int SetPage(std::string page);
+ int SetOverlay(Page* page);
+ const ResourceManager* GetResources();
+
+ // Helper routine for identifing if we're the current page
+ int IsCurrentPage(Page* page);
+
+ // These are routing routines
+ int Render(void);
+ int Update(void);
+ int NotifyTouch(TOUCH_STATE state, int x, int y);
+ int NotifyKey(int key, bool down);
+ int NotifyKeyboard(int key);
+ int SetKeyBoardFocus(int inFocus);
+ int NotifyVarChange(std::string varName, std::string value);
+
+ std::vector<xml_node<>*> styles;
+
+protected:
+ int LoadPages(xml_node<>* pages);
+ int LoadVariables(xml_node<>* vars);
+
+protected:
+ char* mXmlFile;
+ xml_document<> mDoc;
+ ResourceManager* mResources;
+ std::vector<Page*> mPages;
+ std::vector<xml_node<>*> templates;
+ Page* mCurrentPage;
+ std::vector<Page*> mOverlays; // Special case for popup dialogs and the lock screen
+ std::vector<xml_document<>*> mIncludedDocs;
+};
+
+class PageManager
+{
+public:
+ // Used by GUI
+ static int LoadPackage(std::string name, std::string package, std::string startpage);
+ static PageSet* SelectPackage(std::string name);
+ static int ReloadPackage(std::string name, std::string package);
+ static void ReleasePackage(std::string name);
+
+ // Used for actions and pages
+ static int ChangePage(std::string name);
+ static int ChangeOverlay(std::string name);
+ static const ResourceManager* GetResources();
+
+ // Used for console-only mode
+ static int SwitchToConsole(void);
+ static int EndConsole(void);
+
+ // Helper to identify if a particular page is the active page
+ static int IsCurrentPage(Page* page);
+
+ // These are routing routines
+ static int Render(void);
+ static int Update(void);
+ static int NotifyTouch(TOUCH_STATE state, int x, int y);
+ static int NotifyKey(int key, bool down);
+ static int NotifyKeyboard(int key);
+ static int SetKeyBoardFocus(int inFocus);
+ static int NotifyVarChange(std::string varName, std::string value);
+
+ static MouseCursor *GetMouseCursor();
+ static void LoadCursorData(xml_node<>* node);
+
+ static HardwareKeyboard *GetHardwareKeyboard();
+
+ static xml_node<>* FindStyle(std::string name);
+
+protected:
+ static PageSet* FindPackage(std::string name);
+
+protected:
+ static std::map<std::string, PageSet*> mPageSets;
+ static PageSet* mCurrentSet;
+ static PageSet* mBaseSet;
+ static MouseCursor *mMouseCursor;
+ static HardwareKeyboard *mHardwareKeyboard;
+};
+
+#endif // _PAGES_HEADER_HPP
diff --git a/gui/partitionlist.cpp b/gui/partitionlist.cpp
new file mode 100644
index 000000000..102802d7d
--- /dev/null
+++ b/gui/partitionlist.cpp
@@ -0,0 +1,285 @@
+/*
+ Copyright 2013 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+#include <sys/stat.h>
+#include <dirent.h>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../data.hpp"
+#include "../partitions.hpp"
+
+GUIPartitionList::GUIPartitionList(xml_node<>* node) : GUIScrollList(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ mIconSelected = mIconUnselected = NULL;
+ mUpdate = 0;
+ updateList = false;
+
+ child = FindNode(node, "icon");
+ if (child)
+ {
+ mIconSelected = LoadAttrImage(child, "selected");
+ mIconUnselected = LoadAttrImage(child, "unselected");
+ }
+
+ // Handle the result variable
+ child = FindNode(node, "data");
+ if (child)
+ {
+ attr = child->first_attribute("name");
+ if (attr)
+ mVariable = attr->value();
+ attr = child->first_attribute("selectedlist");
+ if (attr)
+ selectedList = attr->value();
+ }
+
+ int iconWidth = std::max(mIconSelected->GetWidth(), mIconUnselected->GetWidth());
+ int iconHeight = std::max(mIconSelected->GetHeight(), mIconUnselected->GetHeight());
+ SetMaxIconSize(iconWidth, iconHeight);
+
+ child = FindNode(node, "listtype");
+ if (child && (attr = child->first_attribute("name"))) {
+ ListType = attr->value();
+ updateList = true;
+ } else {
+ mList.clear();
+ LOGERR("No partition listtype specified for partitionlist GUI element\n");
+ return;
+ }
+}
+
+GUIPartitionList::~GUIPartitionList()
+{
+}
+
+int GUIPartitionList::Update(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ // Check for changes in mount points if the list type is mount and update the list and render if needed
+ if (ListType == "mount") {
+ int listSize = mList.size();
+ for (int i = 0; i < listSize; i++) {
+ if (PartitionManager.Is_Mounted_By_Path(mList.at(i).Mount_Point) && !mList.at(i).selected) {
+ mList.at(i).selected = 1;
+ mUpdate = 1;
+ } else if (!PartitionManager.Is_Mounted_By_Path(mList.at(i).Mount_Point) && mList.at(i).selected) {
+ mList.at(i).selected = 0;
+ mUpdate = 1;
+ }
+ }
+ }
+
+ GUIScrollList::Update();
+
+ if (updateList) {
+ int listSize = 0;
+
+ // Completely update the list if needed -- Used primarily for
+ // restore as the list for restore will change depending on what
+ // partitions were backed up
+ mList.clear();
+ PartitionManager.Get_Partition_List(ListType, &mList);
+ SetVisibleListLocation(0);
+ updateList = false;
+ mUpdate = 1;
+ if (ListType == "backup" || ListType == "flashimg")
+ MatchList();
+ }
+
+ if (mUpdate) {
+ mUpdate = 0;
+ if (Render() == 0)
+ return 2;
+ }
+
+ return 0;
+}
+
+int GUIPartitionList::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIScrollList::NotifyVarChange(varName, value);
+
+ if(!isConditionTrue())
+ return 0;
+
+ if (varName == mVariable && !mUpdate)
+ {
+ if (ListType == "storage") {
+ currentValue = value;
+ SetPosition();
+ } else if (ListType == "backup") {
+ MatchList();
+ } else if (ListType == "restore") {
+ updateList = true;
+ SetVisibleListLocation(0);
+ }
+
+ mUpdate = 1;
+ return 0;
+ }
+ return 0;
+}
+
+void GUIPartitionList::SetPageFocus(int inFocus)
+{
+ GUIScrollList::SetPageFocus(inFocus);
+ if (inFocus) {
+ if (ListType == "storage" || ListType == "flashimg") {
+ DataManager::GetValue(mVariable, currentValue);
+ SetPosition();
+ }
+ updateList = true;
+ mUpdate = 1;
+ }
+}
+
+void GUIPartitionList::MatchList(void) {
+ int i, listSize = mList.size();
+ string variablelist, searchvalue;
+ size_t pos;
+
+ DataManager::GetValue(mVariable, variablelist);
+
+ for (i = 0; i < listSize; i++) {
+ searchvalue = mList.at(i).Mount_Point + ";";
+ pos = variablelist.find(searchvalue);
+ if (pos != string::npos) {
+ mList.at(i).selected = 1;
+ } else {
+ mList.at(i).selected = 0;
+ }
+ }
+}
+
+void GUIPartitionList::SetPosition() {
+ int listSize = mList.size();
+
+ SetVisibleListLocation(0);
+ for (int i = 0; i < listSize; i++) {
+ if (mList.at(i).Mount_Point == currentValue) {
+ mList.at(i).selected = 1;
+ SetVisibleListLocation(i);
+ } else {
+ mList.at(i).selected = 0;
+ }
+ }
+}
+
+size_t GUIPartitionList::GetItemCount()
+{
+ return mList.size();
+}
+
+void GUIPartitionList::RenderItem(size_t itemindex, int yPos, bool selected)
+{
+ // note: the "selected" parameter above is for the currently touched item
+ // don't confuse it with the more persistent "selected" flag per list item used below
+ ImageResource* icon = mList.at(itemindex).selected ? mIconSelected : mIconUnselected;
+ const std::string& text = mList.at(itemindex).Display_Name;
+
+ RenderStdItem(yPos, selected, icon, text.c_str());
+}
+
+void GUIPartitionList::NotifySelect(size_t item_selected)
+{
+ if (item_selected < mList.size()) {
+ int listSize = mList.size();
+ if (ListType == "mount") {
+ if (!mList.at(item_selected).selected) {
+ if (PartitionManager.Mount_By_Path(mList.at(item_selected).Mount_Point, true)) {
+ mList.at(item_selected).selected = 1;
+ PartitionManager.Add_MTP_Storage(mList.at(item_selected).Mount_Point);
+ mUpdate = 1;
+ }
+ } else {
+ if (PartitionManager.UnMount_By_Path(mList.at(item_selected).Mount_Point, true)) {
+ mList.at(item_selected).selected = 0;
+ mUpdate = 1;
+ }
+ }
+ } else if (!mVariable.empty()) {
+ if (ListType == "storage") {
+ int i;
+ std::string str = mList.at(item_selected).Mount_Point;
+ bool update_size = false;
+ TWPartition* Part = PartitionManager.Find_Partition_By_Path(str);
+ if (Part == NULL) {
+ LOGERR("Unable to locate partition for '%s'\n", str.c_str());
+ return;
+ }
+ if (!Part->Is_Mounted() && Part->Removable)
+ update_size = true;
+ if (!Part->Mount(true)) {
+ // Do Nothing
+ } else if (update_size && !Part->Update_Size(true)) {
+ // Do Nothing
+ } else {
+ for (i=0; i<listSize; i++)
+ mList.at(i).selected = 0;
+
+ if (update_size) {
+ char free_space[255];
+ sprintf(free_space, "%llu", Part->Free / 1024 / 1024);
+ mList.at(item_selected).Display_Name = Part->Storage_Name + " (";
+ mList.at(item_selected).Display_Name += free_space;
+ mList.at(item_selected).Display_Name += "MB)";
+ }
+ mList.at(item_selected).selected = 1;
+ mUpdate = 1;
+
+ DataManager::SetValue(mVariable, str);
+ }
+ } else {
+ if (ListType == "flashimg") { // only one item can be selected for flashing images
+ for (int i=0; i<listSize; i++)
+ mList.at(i).selected = 0;
+ }
+ if (mList.at(item_selected).selected)
+ mList.at(item_selected).selected = 0;
+ else
+ mList.at(item_selected).selected = 1;
+
+ int i;
+ string variablelist;
+ for (i=0; i<listSize; i++) {
+ if (mList.at(i).selected) {
+ variablelist += mList.at(i).Mount_Point + ";";
+ }
+ }
+
+ mUpdate = 1;
+ if (selectedList.empty())
+ DataManager::SetValue(mVariable, variablelist);
+ else
+ DataManager::SetValue(selectedList, variablelist);
+ }
+ }
+ }
+}
diff --git a/gui/patternpassword.cpp b/gui/patternpassword.cpp
new file mode 100644
index 000000000..ed152851f
--- /dev/null
+++ b/gui/patternpassword.cpp
@@ -0,0 +1,318 @@
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/types.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUIPatternPassword::GUIPatternPassword(xml_node<>* node)
+ : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ ResetActiveDots();
+ mTrackingTouch = false;
+ mNeedRender = true;
+
+ ConvertStrToColor("blue", &mDotColor);
+ ConvertStrToColor("white", &mActiveDotColor);
+ ConvertStrToColor("blue", &mLineColor);
+
+ mDotImage = mActiveDotImage = NULL;
+ mDotCircle = mActiveDotCircle = NULL;
+ mDotRadius = 50;
+ mLineWidth = 35;
+
+ mAction = NULL;
+ mUpdate = 0;
+
+ if (!node)
+ return;
+
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH, &mPlacement);
+
+ mAction = new GUIAction(node);
+
+ child = FindNode(node, "dot");
+ if(child)
+ {
+ mDotColor = LoadAttrColor(child, "color", mDotColor);
+ mActiveDotColor = LoadAttrColor(child, "activecolor", mActiveDotColor);
+ mDotRadius = LoadAttrIntScaleX(child, "radius", mDotRadius);
+
+ mDotImage = LoadAttrImage(child, "image");
+ mActiveDotImage = LoadAttrImage(child, "activeimage");
+ }
+
+ child = FindNode(node, "line");
+ if(child)
+ {
+ mLineColor = LoadAttrColor(child, "color", mLineColor);
+ mLineWidth = LoadAttrIntScaleX(child, "width", mLineWidth);
+ }
+
+ child = FindNode(node, "data");
+ if(child)
+ mPassVar = LoadAttrString(child, "name", "");
+
+
+ if(!mDotImage || !mDotImage->GetResource() || !mActiveDotImage || !mActiveDotImage->GetResource())
+ {
+ mDotCircle = gr_render_circle(mDotRadius, mDotColor.red, mDotColor.green, mDotColor.blue, mDotColor.alpha);
+ mActiveDotCircle = gr_render_circle(mDotRadius/2, mActiveDotColor.red, mActiveDotColor.green, mActiveDotColor.blue, mActiveDotColor.alpha);
+ }
+ else
+ mDotRadius = mDotImage->GetWidth()/2;
+
+ SetRenderPos(mRenderX, mRenderY, mRenderW, mRenderH);
+}
+
+GUIPatternPassword::~GUIPatternPassword()
+{
+ delete mDotImage;
+ delete mActiveDotImage;
+ delete mAction;
+
+ if(mDotCircle)
+ gr_free_surface(mDotCircle);
+
+ if(mActiveDotCircle)
+ gr_free_surface(mActiveDotCircle);
+}
+
+void GUIPatternPassword::ResetActiveDots()
+{
+ mConnectedDotsLen = 0;
+ mCurLineX = mCurLineY = -1;
+ for(int i = 0; i < 9; ++i)
+ mDots[i].active = false;
+}
+
+int GUIPatternPassword::SetRenderPos(int x, int y, int w, int h)
+{
+ mRenderX = x;
+ mRenderY = y;
+
+ if (w || h)
+ {
+ mRenderW = w;
+ mRenderH = h;
+
+ mAction->SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+ SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+ }
+
+ CalculateDotPositions();
+ return 0;
+}
+
+void GUIPatternPassword::CalculateDotPositions(void)
+{
+ const int step_x = (mRenderW - mDotRadius*2) / 2;
+ const int step_y = (mRenderH - mDotRadius*2) / 2;
+ int x = mRenderX;
+ int y = mRenderY;
+
+ for(int r = 0; r < 3; ++r)
+ {
+ for(int c = 0; c < 3; ++c)
+ {
+ mDots[3*r+c].x = x;
+ mDots[3*r+c].y = y;
+ x += step_x;
+ }
+ x = mRenderX;
+ y += step_y;
+ }
+}
+
+int GUIPatternPassword::Render(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ gr_color(mLineColor.red, mLineColor.green, mLineColor.blue, mLineColor.alpha);
+ for(size_t i = 1; i < mConnectedDotsLen; ++i) {
+ const Dot& dp = mDots[mConnectedDots[i-1]];
+ const Dot& dc = mDots[mConnectedDots[i]];
+ gr_line(dp.x + mDotRadius, dp.y + mDotRadius, dc.x + mDotRadius, dc.y + mDotRadius, mLineWidth);
+ }
+
+ if(mConnectedDotsLen > 0 && mTrackingTouch) {
+ const Dot& dc = mDots[mConnectedDots[mConnectedDotsLen-1]];
+ gr_line(dc.x + mDotRadius, dc.y + mDotRadius, mCurLineX, mCurLineY, mLineWidth);
+ }
+
+ for(int i = 0; i < 9; ++i) {
+ if(mDotCircle) {
+ gr_blit(mDotCircle, 0, 0, gr_get_width(mDotCircle), gr_get_height(mDotCircle), mDots[i].x, mDots[i].y);
+ if(mDots[i].active) {
+ gr_blit(mActiveDotCircle, 0, 0, gr_get_width(mActiveDotCircle), gr_get_height(mActiveDotCircle), mDots[i].x + mDotRadius/2, mDots[i].y + mDotRadius/2);
+ }
+ } else {
+ if(mDots[i].active) {
+ gr_blit(mActiveDotImage->GetResource(), 0, 0, mActiveDotImage->GetWidth(), mActiveDotImage->GetHeight(),
+ mDots[i].x + (mDotRadius - mActiveDotImage->GetWidth()/2), mDots[i].y + (mDotRadius - mActiveDotImage->GetHeight()/2));
+ } else {
+ gr_blit(mDotImage->GetResource(), 0, 0, mDotImage->GetWidth(), mDotImage->GetHeight(), mDots[i].x, mDots[i].y);
+ }
+ }
+ }
+ return 0;
+}
+
+int GUIPatternPassword::Update(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ int res = mNeedRender ? 2 : 1;
+ mNeedRender = false;
+ return res;
+}
+
+bool GUIPatternPassword::IsInRect(int x, int y, int rx, int ry, int rw, int rh)
+{
+ return x >= rx && y >= ry && x <= rx+rw && y <= ry+rh;
+}
+
+int GUIPatternPassword::InDot(int x, int y)
+{
+ for(int i = 0; i < 9; ++i) {
+ if(IsInRect(x, y, mDots[i].x - mDotRadius*1.5, mDots[i].y - mDotRadius*1.5, mDotRadius*6, mDotRadius*6))
+ return i;
+ }
+ return -1;
+}
+
+bool GUIPatternPassword::DotUsed(int dot_idx)
+{
+ for(size_t i = 0; i < mConnectedDotsLen; ++i) {
+ if(mConnectedDots[i] == dot_idx)
+ return true;
+ }
+ return false;
+}
+
+void GUIPatternPassword::ConnectDot(int dot_idx)
+{
+ if(mConnectedDotsLen >= 9)
+ {
+ LOGERR("mConnectedDots in GUIPatternPassword has overflown!\n");
+ return;
+ }
+
+ mConnectedDots[mConnectedDotsLen++] = dot_idx;
+ mDots[dot_idx].active = true;
+}
+
+void GUIPatternPassword::ConnectIntermediateDots(int dot_idx)
+{
+ if(mConnectedDotsLen == 0)
+ return;
+
+ const int last_dot = mConnectedDots[mConnectedDotsLen-1];
+ int mid = -1;
+
+ // The line is vertical and has crossed a point in the middle
+ if(dot_idx%3 == last_dot%3 && abs(dot_idx - last_dot) > 3) {
+ mid = 3 + dot_idx%3;
+ // the line is horizontal and has crossed a point in the middle
+ } else if(dot_idx/3 == last_dot/3 && abs(dot_idx - last_dot) > 1) {
+ mid = (dot_idx/3)*3 + 1;
+ // the line is diagonal and has crossed the middle point
+ } else if((dot_idx == 0 && last_dot == 8) || (dot_idx == 8 && last_dot == 0) ||
+ (dot_idx == 2 && last_dot == 6) || (dot_idx == 6 && last_dot == 2)) {
+ mid = 4;
+ } else {
+ return;
+ }
+
+ if(!DotUsed(mid))
+ ConnectDot(mid);
+}
+
+int GUIPatternPassword::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if(!isConditionTrue())
+ return -1;
+
+ switch (state)
+ {
+ case TOUCH_START:
+ {
+ const int dot_idx = InDot(x, y);
+ if(dot_idx == -1)
+ break;
+
+ mTrackingTouch = true;
+ ResetActiveDots();
+ ConnectDot(dot_idx);
+ DataManager::Vibrate("tw_button_vibrate");
+ mCurLineX = x;
+ mCurLineY = y;
+ mNeedRender = true;
+ break;
+ }
+ case TOUCH_DRAG:
+ {
+ if(!mTrackingTouch)
+ break;
+
+ const int dot_idx = InDot(x, y);
+ if(dot_idx != -1 && !DotUsed(dot_idx))
+ {
+ ConnectIntermediateDots(dot_idx);
+ ConnectDot(dot_idx);
+ DataManager::Vibrate("tw_button_vibrate");
+ }
+
+ mCurLineX = x;
+ mCurLineY = y;
+ mNeedRender = true;
+ break;
+ }
+ case TOUCH_RELEASE:
+ {
+ if(!mTrackingTouch)
+ break;
+
+ mNeedRender = true;
+ mTrackingTouch = false;
+ PatternDrawn();
+ ResetActiveDots();
+ break;
+ }
+ default:
+ break;
+ }
+ return 0;
+}
+
+void GUIPatternPassword::PatternDrawn()
+{
+ if(!mPassVar.empty() && mConnectedDotsLen > 0)
+ {
+ std::string pass;
+ for(size_t i = 0; i < mConnectedDotsLen; ++i)
+ pass += '1' + mConnectedDots[i];
+ DataManager::SetValue(mPassVar, pass);
+ }
+
+ if(mAction)
+ mAction->doActions();
+}
diff --git a/gui/progressbar.cpp b/gui/progressbar.cpp
new file mode 100644
index 000000000..a478a40d0
--- /dev/null
+++ b/gui/progressbar.cpp
@@ -0,0 +1,226 @@
+// progressbar.cpp - GUIProgressBar object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUIProgressBar::GUIProgressBar(xml_node<>* node) : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ mEmptyBar = NULL;
+ mFullBar = NULL;
+ mLastPos = 0;
+ mSlide = 0.0;
+ mSlideInc = 0.0;
+
+ if (!node)
+ {
+ LOGERR("GUIProgressBar created without XML node\n");
+ return;
+ }
+
+ child = FindNode(node, "resource");
+ if (child)
+ {
+ mEmptyBar = LoadAttrImage(child, "empty");
+ mFullBar = LoadAttrImage(child, "full");
+ }
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY);
+
+ // Load the data
+ child = FindNode(node, "data");
+ if (child)
+ {
+ mMinValVar = LoadAttrString(child, "min");
+ mMaxValVar = LoadAttrString(child, "max");
+ mCurValVar = LoadAttrString(child, "name");
+ }
+
+ mRenderW = mEmptyBar->GetWidth();
+ mRenderH = mEmptyBar->GetHeight();
+}
+
+int GUIProgressBar::Render(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ // This handles making sure timing updates occur
+ Update();
+ return RenderInternal();
+}
+
+int GUIProgressBar::RenderInternal(void)
+{
+ if (!mEmptyBar || !mEmptyBar->GetResource())
+ return -1;
+
+ if (!mFullBar || !mFullBar->GetResource())
+ return -1;
+
+ gr_blit(mEmptyBar->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
+ gr_blit(mFullBar->GetResource(), 0, 0, mLastPos, mRenderH, mRenderX, mRenderY);
+ return 0;
+}
+
+int GUIProgressBar::Update(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ std::string str;
+ int min, max, cur, pos;
+
+ if (mMinValVar.empty())
+ min = 0;
+ else
+ {
+ str.clear();
+ if (atoi(mMinValVar.c_str()) != 0)
+ str = mMinValVar;
+ else
+ DataManager::GetValue(mMinValVar, str);
+ min = atoi(str.c_str());
+ }
+
+ if (mMaxValVar.empty())
+ max = 100;
+ else
+ {
+ str.clear();
+ if (atoi(mMaxValVar.c_str()) != 0)
+ str = mMaxValVar;
+ else
+ DataManager::GetValue(mMaxValVar, str);
+ max = atoi(str.c_str());
+ }
+
+ str.clear();
+ DataManager::GetValue(mCurValVar, str);
+ cur = atoi(str.c_str());
+
+ // Do slide, if needed
+ if (mSlideFrames)
+ {
+ mSlide += mSlideInc;
+ mSlideFrames--;
+ if (cur != (int) mSlide)
+ {
+ cur = (int) mSlide;
+ DataManager::SetValue(mCurValVar, cur);
+ }
+ }
+
+ // Normalize to 0
+ max -= min;
+ cur -= min;
+ min = 0;
+
+ if (cur < min)
+ cur = min;
+ if (cur > max)
+ cur = max;
+
+ if (max == 0)
+ pos = 0;
+ else
+ pos = (cur * mRenderW) / max;
+
+ if (pos == mLastPos)
+ return 0;
+
+ mLastPos = pos;
+
+ if (RenderInternal() != 0)
+ return -1;
+ return 2;
+}
+
+int GUIProgressBar::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIObject::NotifyVarChange(varName, value);
+
+ if(!isConditionTrue())
+ return 0;
+
+ static int nextPush = 0;
+
+ if (varName.empty())
+ {
+ nextPush = 0;
+ mLastPos = 0;
+ mSlide = 0.0;
+ mSlideInc = 0.0;
+ return 0;
+ }
+
+ if (varName == "ui_progress_portion" || varName == "ui_progress_frames")
+ {
+ std::string str;
+ int cur;
+
+ if (mSlideFrames)
+ {
+ mSlide += (mSlideInc * mSlideFrames);
+ cur = (int) mSlide;
+ DataManager::SetValue(mCurValVar, cur);
+ mSlideFrames = 0;
+ }
+
+ if (nextPush)
+ {
+ mSlide += nextPush;
+ cur = (int) mSlide;
+ DataManager::SetValue(mCurValVar, cur);
+ nextPush = 0;
+ }
+
+ if (varName == "ui_progress_portion") mSlide = atof(value.c_str());
+ else
+ {
+ mSlideFrames = atol(value.c_str());
+ if (mSlideFrames == 0)
+ {
+ // We're just holding this progress until the next push
+ nextPush = mSlide;
+ }
+ }
+
+ if (mSlide > 0 && mSlideFrames > 0)
+ {
+ // Get the current position
+ str.clear();
+ DataManager::GetValue(mCurValVar, str);
+ cur = atoi(str.c_str());
+
+ mSlideInc = (float) mSlide / (float) mSlideFrames;
+ mSlide = cur;
+ }
+ }
+ return 0;
+}
diff --git a/gui/rapidxml.hpp b/gui/rapidxml.hpp
new file mode 100644
index 000000000..c0a7be44e
--- /dev/null
+++ b/gui/rapidxml.hpp
@@ -0,0 +1,2616 @@
+#ifndef RAPIDXML_HPP_INCLUDED
+#define RAPIDXML_HPP_INCLUDED
+
+#define RAPIDXML_NO_EXCEPTIONS
+
+// Copyright (C) 2006, 2009 Marcin Kalicinski
+// Version 1.13
+// Revision $DateTime: 2009/05/13 01:46:17 $
+//! \file rapidxml.hpp This file contains rapidxml parser and DOM implementation
+
+// If standard library is disabled, user must provide implementations of required functions and typedefs
+#if !defined(RAPIDXML_NO_STDLIB)
+ #include <cstdlib> // For std::size_t
+ #include <cassert> // For assert
+ #include <new> // For placement new
+#endif
+
+// On MSVC, disable "conditional expression is constant" warning (level 4).
+// This warning is almost impossible to avoid with certain types of templated code
+#ifdef _MSC_VER
+ #pragma warning(push)
+ #pragma warning(disable:4127) // Conditional expression is constant
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// RAPIDXML_PARSE_ERROR
+
+#if defined(RAPIDXML_NO_EXCEPTIONS)
+
+#define RAPIDXML_PARSE_ERROR(what, where) { parse_error_handler(what, where); assert(0); }
+
+namespace rapidxml
+{
+ //! When exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS,
+ //! this function is called to notify user about the error.
+ //! It must be defined by the user.
+ //! <br><br>
+ //! This function cannot return. If it does, the results are undefined.
+ //! <br><br>
+ //! A very simple definition might look like that:
+ //! <pre>
+ //! void %rapidxml::%parse_error_handler(const char *what, void *where)
+ //! {
+ //! std::cout << "Parse error: " << what << "\n";
+ //! std::abort();
+ //! }
+ //! </pre>
+ //! \param what Human readable description of the error.
+ //! \param where Pointer to character data where error was detected.
+ void parse_error_handler(const char *what, void *where);
+}
+
+#else
+
+#include <exception> // For std::exception
+
+#define RAPIDXML_PARSE_ERROR(what, where) throw parse_error(what, where)
+
+namespace rapidxml
+{
+
+ //! Parse error exception.
+ //! This exception is thrown by the parser when an error occurs.
+ //! Use what() function to get human-readable error message.
+ //! Use where() function to get a pointer to position within source text where error was detected.
+ //! <br><br>
+ //! If throwing exceptions by the parser is undesirable,
+ //! it can be disabled by defining RAPIDXML_NO_EXCEPTIONS macro before rapidxml.hpp is included.
+ //! This will cause the parser to call rapidxml::parse_error_handler() function instead of throwing an exception.
+ //! This function must be defined by the user.
+ //! <br><br>
+ //! This class derives from <code>std::exception</code> class.
+ class parse_error: public std::exception
+ {
+
+ public:
+
+ //! Constructs parse error
+ parse_error(const char *what, void *where)
+ : m_what(what)
+ , m_where(where)
+ {
+ }
+
+ //! Gets human readable description of error.
+ //! \return Pointer to null terminated description of the error.
+ virtual const char *what() const throw()
+ {
+ return m_what;
+ }
+
+ //! Gets pointer to character data where error happened.
+ //! Ch should be the same as char type of xml_document that produced the error.
+ //! \return Pointer to location within the parsed string where error occured.
+ template<class Ch>
+ Ch *where() const
+ {
+ return reinterpret_cast<Ch *>(m_where);
+ }
+
+ private:
+
+ const char *m_what;
+ void *m_where;
+
+ };
+}
+
+#endif
+
+///////////////////////////////////////////////////////////////////////////
+// Pool sizes
+
+#ifndef RAPIDXML_STATIC_POOL_SIZE
+ // Size of static memory block of memory_pool.
+ // Define RAPIDXML_STATIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+ // No dynamic memory allocations are performed by memory_pool until static memory is exhausted.
+ #define RAPIDXML_STATIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_DYNAMIC_POOL_SIZE
+ // Size of dynamic memory block of memory_pool.
+ // Define RAPIDXML_DYNAMIC_POOL_SIZE before including rapidxml.hpp if you want to override the default value.
+ // After the static block is exhausted, dynamic blocks with approximately this size are allocated by memory_pool.
+ #define RAPIDXML_DYNAMIC_POOL_SIZE (64 * 1024)
+#endif
+
+#ifndef RAPIDXML_ALIGNMENT
+ // Memory allocation alignment.
+ // Define RAPIDXML_ALIGNMENT before including rapidxml.hpp if you want to override the default value, which is the size of pointer.
+ // All memory allocations for nodes, attributes and strings will be aligned to this value.
+ // This must be a power of 2 and at least 1, otherwise memory_pool will not work.
+ #define RAPIDXML_ALIGNMENT sizeof(void *)
+#endif
+
+namespace rapidxml
+{
+ // Forward declarations
+ template<class Ch> class xml_node;
+ template<class Ch> class xml_attribute;
+ template<class Ch> class xml_document;
+
+ //! Enumeration listing all node types produced by the parser.
+ //! Use xml_node::type() function to query node type.
+ enum node_type
+ {
+ node_document, //!< A document node. Name and value are empty.
+ node_element, //!< An element node. Name contains element name. Value contains text of first data node.
+ node_data, //!< A data node. Name is empty. Value contains data text.
+ node_cdata, //!< A CDATA node. Name is empty. Value contains data text.
+ node_comment, //!< A comment node. Name is empty. Value contains comment text.
+ node_declaration, //!< A declaration node. Name and value are empty. Declaration parameters (version, encoding and standalone) are in node attributes.
+ node_doctype, //!< A DOCTYPE node. Name is empty. Value contains DOCTYPE text.
+ node_pi //!< A PI node. Name contains target. Value contains instructions.
+ };
+
+ ///////////////////////////////////////////////////////////////////////
+ // Parsing flags
+
+ //! Parse flag instructing the parser to not create data nodes.
+ //! Text of first data node will still be placed in value of parent element, unless rapidxml::parse_no_element_values flag is also specified.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_data_nodes = 0x1;
+
+ //! Parse flag instructing the parser to not use text of first data node as a value of parent element.
+ //! Can be combined with other flags by use of | operator.
+ //! Note that child data nodes of element node take precendence over its value when printing.
+ //! That is, if element has one or more child data nodes <em>and</em> a value, the value will be ignored.
+ //! Use rapidxml::parse_no_data_nodes flag to prevent creation of data nodes if you want to manipulate data using values of elements.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_element_values = 0x2;
+
+ //! Parse flag instructing the parser to not place zero terminators after strings in the source text.
+ //! By default zero terminators are placed, modifying source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_string_terminators = 0x4;
+
+ //! Parse flag instructing the parser to not translate entities in the source text.
+ //! By default entities are translated, modifying source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_entity_translation = 0x8;
+
+ //! Parse flag instructing the parser to disable UTF-8 handling and assume plain 8 bit characters.
+ //! By default, UTF-8 handling is enabled.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_no_utf8 = 0x10;
+
+ //! Parse flag instructing the parser to create XML declaration node.
+ //! By default, declaration node is not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_declaration_node = 0x20;
+
+ //! Parse flag instructing the parser to create comments nodes.
+ //! By default, comment nodes are not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_comment_nodes = 0x40;
+
+ //! Parse flag instructing the parser to create DOCTYPE node.
+ //! By default, doctype node is not created.
+ //! Although W3C specification allows at most one DOCTYPE node, RapidXml will silently accept documents with more than one.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_doctype_node = 0x80;
+
+ //! Parse flag instructing the parser to create PI nodes.
+ //! By default, PI nodes are not created.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_pi_nodes = 0x100;
+
+ //! Parse flag instructing the parser to validate closing tag names.
+ //! If not set, name inside closing tag is irrelevant to the parser.
+ //! By default, closing tags are not validated.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_validate_closing_tags = 0x200;
+
+ //! Parse flag instructing the parser to trim all leading and trailing whitespace of data nodes.
+ //! By default, whitespace is not trimmed.
+ //! This flag does not cause the parser to modify source text.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_trim_whitespace = 0x400;
+
+ //! Parse flag instructing the parser to condense all whitespace runs of data nodes to a single space character.
+ //! Trimming of leading and trailing whitespace of data is controlled by rapidxml::parse_trim_whitespace flag.
+ //! By default, whitespace is not normalized.
+ //! If this flag is specified, source text will be modified.
+ //! Can be combined with other flags by use of | operator.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_normalize_whitespace = 0x800;
+
+ // Compound flags
+
+ //! Parse flags which represent default behaviour of the parser.
+ //! This is always equal to 0, so that all other flags can be simply ored together.
+ //! Normally there is no need to inconveniently disable flags by anding with their negated (~) values.
+ //! This also means that meaning of each flag is a <i>negation</i> of the default setting.
+ //! For example, if flag name is rapidxml::parse_no_utf8, it means that utf-8 is <i>enabled</i> by default,
+ //! and using the flag will disable it.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_default = 0;
+
+ //! A combination of parse flags that forbids any modifications of the source text.
+ //! This also results in faster parsing. However, note that the following will occur:
+ //! <ul>
+ //! <li>names and values of nodes will not be zero terminated, you have to use xml_base::name_size() and xml_base::value_size() functions to determine where name and value ends</li>
+ //! <li>entities will not be translated</li>
+ //! <li>whitespace will not be normalized</li>
+ //! </ul>
+ //! See xml_document::parse() function.
+ const int parse_non_destructive = parse_no_string_terminators | parse_no_entity_translation;
+
+ //! A combination of parse flags resulting in fastest possible parsing, without sacrificing important data.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_fastest = parse_non_destructive | parse_no_data_nodes;
+
+ //! A combination of parse flags resulting in largest amount of data being extracted.
+ //! This usually results in slowest parsing.
+ //! <br><br>
+ //! See xml_document::parse() function.
+ const int parse_full = parse_declaration_node | parse_comment_nodes | parse_doctype_node | parse_pi_nodes | parse_validate_closing_tags;
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internals
+
+ //! \cond internal
+ namespace internal
+ {
+
+ // Struct that contains lookup tables for the parser
+ // It must be a template to allow correct linking (because it has static data members, which are defined in a header file).
+ template<int Dummy>
+ struct lookup_tables
+ {
+ static const unsigned char lookup_whitespace[256]; // Whitespace table
+ static const unsigned char lookup_node_name[256]; // Node name table
+ static const unsigned char lookup_text[256]; // Text table
+ static const unsigned char lookup_text_pure_no_ws[256]; // Text table
+ static const unsigned char lookup_text_pure_with_ws[256]; // Text table
+ static const unsigned char lookup_attribute_name[256]; // Attribute name table
+ static const unsigned char lookup_attribute_data_1[256]; // Attribute data table with single quote
+ static const unsigned char lookup_attribute_data_1_pure[256]; // Attribute data table with single quote
+ static const unsigned char lookup_attribute_data_2[256]; // Attribute data table with double quotes
+ static const unsigned char lookup_attribute_data_2_pure[256]; // Attribute data table with double quotes
+ static const unsigned char lookup_digits[256]; // Digits
+ static const unsigned char lookup_upcase[256]; // To uppercase conversion table for ASCII characters
+ };
+
+ // Find length of the string
+ template<class Ch>
+ inline std::size_t measure(const Ch *p)
+ {
+ const Ch *tmp = p;
+ while (*tmp)
+ ++tmp;
+ return tmp - p;
+ }
+
+ // Compare strings for equality
+ template<class Ch>
+ inline bool compare(const Ch *p1, std::size_t size1, const Ch *p2, std::size_t size2, bool case_sensitive)
+ {
+ if (size1 != size2)
+ return false;
+ if (case_sensitive)
+ {
+ for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+ if (*p1 != *p2)
+ return false;
+ }
+ else
+ {
+ for (const Ch *end = p1 + size1; p1 < end; ++p1, ++p2)
+ if (lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p1)] != lookup_tables<0>::lookup_upcase[static_cast<unsigned char>(*p2)])
+ return false;
+ }
+ return true;
+ }
+ }
+ //! \endcond
+
+ ///////////////////////////////////////////////////////////////////////
+ // Memory pool
+
+ //! This class is used by the parser to create new nodes and attributes, without overheads of dynamic memory allocation.
+ //! In most cases, you will not need to use this class directly.
+ //! However, if you need to create nodes manually or modify names/values of nodes,
+ //! you are encouraged to use memory_pool of relevant xml_document to allocate the memory.
+ //! Not only is this faster than allocating them by using <code>new</code> operator,
+ //! but also their lifetime will be tied to the lifetime of document,
+ //! possibly simplyfing memory management.
+ //! <br><br>
+ //! Call allocate_node() or allocate_attribute() functions to obtain new nodes or attributes from the pool.
+ //! You can also call allocate_string() function to allocate strings.
+ //! Such strings can then be used as names or values of nodes without worrying about their lifetime.
+ //! Note that there is no <code>free()</code> function -- all allocations are freed at once when clear() function is called,
+ //! or when the pool is destroyed.
+ //! <br><br>
+ //! It is also possible to create a standalone memory_pool, and use it
+ //! to allocate nodes, whose lifetime will not be tied to any document.
+ //! <br><br>
+ //! Pool maintains <code>RAPIDXML_STATIC_POOL_SIZE</code> bytes of statically allocated memory.
+ //! Until static memory is exhausted, no dynamic memory allocations are done.
+ //! When static memory is exhausted, pool allocates additional blocks of memory of size <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> each,
+ //! by using global <code>new[]</code> and <code>delete[]</code> operators.
+ //! This behaviour can be changed by setting custom allocation routines.
+ //! Use set_allocator() function to set them.
+ //! <br><br>
+ //! Allocations for nodes, attributes and strings are aligned at <code>RAPIDXML_ALIGNMENT</code> bytes.
+ //! This value defaults to the size of pointer on target architecture.
+ //! <br><br>
+ //! To obtain absolutely top performance from the parser,
+ //! it is important that all nodes are allocated from a single, contiguous block of memory.
+ //! Otherwise, cache misses when jumping between two (or more) disjoint blocks of memory can slow down parsing quite considerably.
+ //! If required, you can tweak <code>RAPIDXML_STATIC_POOL_SIZE</code>, <code>RAPIDXML_DYNAMIC_POOL_SIZE</code> and <code>RAPIDXML_ALIGNMENT</code>
+ //! to obtain best wasted memory to performance compromise.
+ //! To do it, define their values before rapidxml.hpp file is included.
+ //! \param Ch Character type of created nodes.
+ template<class Ch = char>
+ class memory_pool
+ {
+
+ public:
+
+ //! \cond internal
+ typedef void *(alloc_func)(std::size_t); // Type of user-defined function used to allocate memory
+ typedef void (free_func)(void *); // Type of user-defined function used to free memory
+ //! \endcond
+
+ //! Constructs empty pool with default allocator functions.
+ memory_pool()
+ : m_alloc_func(0)
+ , m_free_func(0)
+ {
+ init();
+ }
+
+ //! Destroys pool and frees all the memory.
+ //! This causes memory occupied by nodes allocated by the pool to be freed.
+ //! Nodes allocated from the pool are no longer valid.
+ ~memory_pool()
+ {
+ clear();
+ }
+
+ //! Allocates a new node from the pool, and optionally assigns name and value to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param type Type of node to create.
+ //! \param name Name to assign to the node, or 0 to assign no name.
+ //! \param value Value to assign to the node, or 0 to assign no value.
+ //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+ //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+ //! \return Pointer to allocated node. This pointer will never be NULL.
+ xml_node<Ch> *allocate_node(node_type type,
+ const Ch *name = 0, const Ch *value = 0,
+ std::size_t name_size = 0, std::size_t value_size = 0)
+ {
+ void *memory = allocate_aligned(sizeof(xml_node<Ch>));
+ xml_node<Ch> *node = new(memory) xml_node<Ch>(type);
+ if (name)
+ {
+ if (name_size > 0)
+ node->name(name, name_size);
+ else
+ node->name(name);
+ }
+ if (value)
+ {
+ if (value_size > 0)
+ node->value(value, value_size);
+ else
+ node->value(value);
+ }
+ return node;
+ }
+
+ //! Allocates a new attribute from the pool, and optionally assigns name and value to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param name Name to assign to the attribute, or 0 to assign no name.
+ //! \param value Value to assign to the attribute, or 0 to assign no value.
+ //! \param name_size Size of name to assign, or 0 to automatically calculate size from name string.
+ //! \param value_size Size of value to assign, or 0 to automatically calculate size from value string.
+ //! \return Pointer to allocated attribute. This pointer will never be NULL.
+ xml_attribute<Ch> *allocate_attribute(const Ch *name = 0, const Ch *value = 0,
+ std::size_t name_size = 0, std::size_t value_size = 0)
+ {
+ void *memory = allocate_aligned(sizeof(xml_attribute<Ch>));
+ xml_attribute<Ch> *attribute = new(memory) xml_attribute<Ch>;
+ if (name)
+ {
+ if (name_size > 0)
+ attribute->name(name, name_size);
+ else
+ attribute->name(name);
+ }
+ if (value)
+ {
+ if (value_size > 0)
+ attribute->value(value, value_size);
+ else
+ attribute->value(value);
+ }
+ return attribute;
+ }
+
+ //! Allocates a char array of given size from the pool, and optionally copies a given string to it.
+ //! If the allocation request cannot be accomodated, this function will throw <code>std::bad_alloc</code>.
+ //! If exceptions are disabled by defining RAPIDXML_NO_EXCEPTIONS, this function
+ //! will call rapidxml::parse_error_handler() function.
+ //! \param source String to initialize the allocated memory with, or 0 to not initialize it.
+ //! \param size Number of characters to allocate, or zero to calculate it automatically from source string length; if size is 0, source string must be specified and null terminated.
+ //! \return Pointer to allocated char array. This pointer will never be NULL.
+ Ch *allocate_string(const Ch *source = 0, std::size_t size = 0)
+ {
+ assert(source || size); // Either source or size (or both) must be specified
+ if (size == 0)
+ size = internal::measure(source) + 1;
+ Ch *result = static_cast<Ch *>(allocate_aligned(size * sizeof(Ch)));
+ if (source)
+ for (std::size_t i = 0; i < size; ++i)
+ result[i] = source[i];
+ return result;
+ }
+
+ //! Clones an xml_node and its hierarchy of child nodes and attributes.
+ //! Nodes and attributes are allocated from this memory pool.
+ //! Names and values are not cloned, they are shared between the clone and the source.
+ //! Result node can be optionally specified as a second parameter,
+ //! in which case its contents will be replaced with cloned source node.
+ //! This is useful when you want to clone entire document.
+ //! \param source Node to clone.
+ //! \param result Node to put results in, or 0 to automatically allocate result node
+ //! \return Pointer to cloned node. This pointer will never be NULL.
+ xml_node<Ch> *clone_node(const xml_node<Ch> *source, xml_node<Ch> *result = 0)
+ {
+ // Prepare result node
+ if (result)
+ {
+ result->remove_all_attributes();
+ result->remove_all_nodes();
+ result->type(source->type());
+ }
+ else
+ result = allocate_node(source->type());
+
+ // Clone name and value
+ result->name(source->name(), source->name_size());
+ result->value(source->value(), source->value_size());
+
+ // Clone child nodes and attributes
+ for (xml_node<Ch> *child = source->first_node(); child; child = child->next_sibling())
+ result->append_node(clone_node(child));
+ for (xml_attribute<Ch> *attr = source->first_attribute(); attr; attr = attr->next_attribute())
+ result->append_attribute(allocate_attribute(attr->name(), attr->value(), attr->name_size(), attr->value_size()));
+
+ return result;
+ }
+
+ //! Clears the pool.
+ //! This causes memory occupied by nodes allocated by the pool to be freed.
+ //! Any nodes or strings allocated from the pool will no longer be valid.
+ void clear()
+ {
+ while (m_begin != m_static_memory)
+ {
+ char *previous_begin = reinterpret_cast<header *>(align(m_begin))->previous_begin;
+ if (m_free_func)
+ m_free_func(m_begin);
+ else
+ delete[] m_begin;
+ m_begin = previous_begin;
+ }
+ init();
+ }
+
+ //! Sets or resets the user-defined memory allocation functions for the pool.
+ //! This can only be called when no memory is allocated from the pool yet, otherwise results are undefined.
+ //! Allocation function must not return invalid pointer on failure. It should either throw,
+ //! stop the program, or use <code>longjmp()</code> function to pass control to other place of program.
+ //! If it returns invalid pointer, results are undefined.
+ //! <br><br>
+ //! User defined allocation functions must have the following forms:
+ //! <br><code>
+ //! <br>void *allocate(std::size_t size);
+ //! <br>void free(void *pointer);
+ //! </code><br>
+ //! \param af Allocation function, or 0 to restore default function
+ //! \param ff Free function, or 0 to restore default function
+ void set_allocator(alloc_func *af, free_func *ff)
+ {
+ assert(m_begin == m_static_memory && m_ptr == align(m_begin)); // Verify that no memory is allocated yet
+ m_alloc_func = af;
+ m_free_func = ff;
+ }
+
+ private:
+
+ struct header
+ {
+ char *previous_begin;
+ };
+
+ void init()
+ {
+ m_begin = m_static_memory;
+ m_ptr = align(m_begin);
+ m_end = m_static_memory + sizeof(m_static_memory);
+ }
+
+ char *align(char *ptr)
+ {
+ std::size_t alignment = ((RAPIDXML_ALIGNMENT - (std::size_t(ptr) & (RAPIDXML_ALIGNMENT - 1))) & (RAPIDXML_ALIGNMENT - 1));
+ return ptr + alignment;
+ }
+
+ char *allocate_raw(std::size_t size)
+ {
+ // Allocate
+ void *memory;
+ if (m_alloc_func) // Allocate memory using either user-specified allocation function or global operator new[]
+ {
+ memory = m_alloc_func(size);
+ assert(memory); // Allocator is not allowed to return 0, on failure it must either throw, stop the program or use longjmp
+ }
+ else
+ {
+ memory = new char[size];
+#ifdef RAPIDXML_NO_EXCEPTIONS
+ if (!memory) // If exceptions are disabled, verify memory allocation, because new will not be able to throw bad_alloc
+ RAPIDXML_PARSE_ERROR("out of memory", 0);
+#endif
+ }
+ return static_cast<char *>(memory);
+ }
+
+ void *allocate_aligned(std::size_t size)
+ {
+ // Calculate aligned pointer
+ char *result = align(m_ptr);
+
+ // If not enough memory left in current pool, allocate a new pool
+ if (result + size > m_end)
+ {
+ // Calculate required pool size (may be bigger than RAPIDXML_DYNAMIC_POOL_SIZE)
+ std::size_t pool_size = RAPIDXML_DYNAMIC_POOL_SIZE;
+ if (pool_size < size)
+ pool_size = size;
+
+ // Allocate
+ std::size_t alloc_size = sizeof(header) + (2 * RAPIDXML_ALIGNMENT - 2) + pool_size; // 2 alignments required in worst case: one for header, one for actual allocation
+ char *raw_memory = allocate_raw(alloc_size);
+
+ // Setup new pool in allocated memory
+ char *pool = align(raw_memory);
+ header *new_header = reinterpret_cast<header *>(pool);
+ new_header->previous_begin = m_begin;
+ m_begin = raw_memory;
+ m_ptr = pool + sizeof(header);
+ m_end = raw_memory + alloc_size;
+
+ // Calculate aligned pointer again using new pool
+ result = align(m_ptr);
+ }
+
+ // Update pool and return aligned pointer
+ m_ptr = result + size;
+ return result;
+ }
+
+ char *m_begin; // Start of raw memory making up current pool
+ char *m_ptr; // First free byte in current pool
+ char *m_end; // One past last available byte in current pool
+ char m_static_memory[RAPIDXML_STATIC_POOL_SIZE]; // Static raw memory
+ alloc_func *m_alloc_func; // Allocator function, or 0 if default is to be used
+ free_func *m_free_func; // Free function, or 0 if default is to be used
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML base
+
+ //! Base class for xml_node and xml_attribute implementing common functions:
+ //! name(), name_size(), value(), value_size() and parent().
+ //! \param Ch Character type to use
+ template<class Ch = char>
+ class xml_base
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ // Construct a base with empty name, value and parent
+ xml_base()
+ : m_name(0)
+ , m_value(0)
+ , m_parent(0)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node data access
+
+ //! Gets name of the node.
+ //! Interpretation of name depends on type of node.
+ //! Note that name will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+ //! <br><br>
+ //! Use name_size() function to determine length of the name.
+ //! \return Name of node, or empty string if node has no name.
+ Ch *name() const
+ {
+ return m_name ? m_name : nullstr();
+ }
+
+ //! Gets size of node name, not including terminator character.
+ //! This function works correctly irrespective of whether name is or is not zero terminated.
+ //! \return Size of node name, in characters.
+ std::size_t name_size() const
+ {
+ return m_name ? m_name_size : 0;
+ }
+
+ //! Gets value of node.
+ //! Interpretation of value depends on type of node.
+ //! Note that value will not be zero-terminated if rapidxml::parse_no_string_terminators option was selected during parse.
+ //! <br><br>
+ //! Use value_size() function to determine length of the value.
+ //! \return Value of node, or empty string if node has no value.
+ Ch *value() const
+ {
+ return m_value ? m_value : nullstr();
+ }
+
+ //! Gets size of node value, not including terminator character.
+ //! This function works correctly irrespective of whether value is or is not zero terminated.
+ //! \return Size of node value, in characters.
+ std::size_t value_size() const
+ {
+ return m_value ? m_value_size : 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node modification
+
+ //! Sets name of node to a non zero-terminated string.
+ //! See \ref ownership_of_strings.
+ //! <br><br>
+ //! Note that node does not own its name or value, it only stores a pointer to it.
+ //! It will not delete or otherwise free the pointer on destruction.
+ //! It is reponsibility of the user to properly manage lifetime of the string.
+ //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+ //! on destruction of the document the string will be automatically freed.
+ //! <br><br>
+ //! Size of name must be specified separately, because name does not have to be zero terminated.
+ //! Use name(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+ //! \param name Name of node to set. Does not have to be zero terminated.
+ //! \param size Size of name, in characters. This does not include zero terminator, if one is present.
+ void name(const Ch *name, std::size_t size)
+ {
+ m_name = const_cast<Ch *>(name);
+ m_name_size = size;
+ }
+
+ //! Sets name of node to a zero-terminated string.
+ //! See also \ref ownership_of_strings and xml_node::name(const Ch *, std::size_t).
+ //! \param name Name of node to set. Must be zero terminated.
+ void name(const Ch *name)
+ {
+ this->name(name, internal::measure(name));
+ }
+
+ //! Sets value of node to a non zero-terminated string.
+ //! See \ref ownership_of_strings.
+ //! <br><br>
+ //! Note that node does not own its name or value, it only stores a pointer to it.
+ //! It will not delete or otherwise free the pointer on destruction.
+ //! It is reponsibility of the user to properly manage lifetime of the string.
+ //! The easiest way to achieve it is to use memory_pool of the document to allocate the string -
+ //! on destruction of the document the string will be automatically freed.
+ //! <br><br>
+ //! Size of value must be specified separately, because it does not have to be zero terminated.
+ //! Use value(const Ch *) function to have the length automatically calculated (string must be zero terminated).
+ //! <br><br>
+ //! If an element has a child node of type node_data, it will take precedence over element value when printing.
+ //! If you want to manipulate data of elements using values, use parser flag rapidxml::parse_no_data_nodes to prevent creation of data nodes by the parser.
+ //! \param value value of node to set. Does not have to be zero terminated.
+ //! \param size Size of value, in characters. This does not include zero terminator, if one is present.
+ void value(const Ch *value, std::size_t size)
+ {
+ m_value = const_cast<Ch *>(value);
+ m_value_size = size;
+ }
+
+ //! Sets value of node to a zero-terminated string.
+ //! See also \ref ownership_of_strings and xml_node::value(const Ch *, std::size_t).
+ //! \param value Vame of node to set. Must be zero terminated.
+ void value(const Ch *value)
+ {
+ this->value(value, internal::measure(value));
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets node parent.
+ //! \return Pointer to parent node, or 0 if there is no parent.
+ xml_node<Ch> *parent() const
+ {
+ return m_parent;
+ }
+
+ protected:
+
+ // Return empty string
+ static Ch *nullstr()
+ {
+ static Ch zero = Ch('\0');
+ return &zero;
+ }
+
+ Ch *m_name; // Name of node, or 0 if no name
+ Ch *m_value; // Value of node, or 0 if no value
+ std::size_t m_name_size; // Length of node name, or undefined of no name
+ std::size_t m_value_size; // Length of node value, or undefined if no value
+ xml_node<Ch> *m_parent; // Pointer to parent node, or 0 if none
+
+ };
+
+ //! Class representing attribute node of XML document.
+ //! Each attribute has name and value strings, which are available through name() and value() functions (inherited from xml_base).
+ //! Note that after parse, both name and value of attribute will point to interior of source text used for parsing.
+ //! Thus, this text must persist in memory for the lifetime of attribute.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_attribute: public xml_base<Ch>
+ {
+
+ friend class xml_node<Ch>;
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ //! Constructs an empty attribute with the specified type.
+ //! Consider using memory_pool of appropriate xml_document if allocating attributes manually.
+ xml_attribute()
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets document of which attribute is a child.
+ //! \return Pointer to document that contains this attribute, or 0 if there is no parent document.
+ xml_document<Ch> *document() const
+ {
+ if (xml_node<Ch> *node = this->parent())
+ {
+ while (node->parent())
+ node = node->parent();
+ return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+ }
+ else
+ return 0;
+ }
+
+ //! Gets previous attribute, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return previous attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *previous_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_prev_attribute; attribute; attribute = attribute->m_prev_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return this->m_parent ? m_prev_attribute : 0;
+ }
+
+ //! Gets next attribute, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return next attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *next_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_next_attribute; attribute; attribute = attribute->m_next_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return this->m_parent ? m_next_attribute : 0;
+ }
+
+ private:
+
+ xml_attribute<Ch> *m_prev_attribute; // Pointer to previous sibling of attribute, or 0 if none; only valid if parent is non-zero
+ xml_attribute<Ch> *m_next_attribute; // Pointer to next sibling of attribute, or 0 if none; only valid if parent is non-zero
+
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML node
+
+ //! Class representing a node of XML document.
+ //! Each node may have associated name and value strings, which are available through name() and value() functions.
+ //! Interpretation of name and value depends on type of the node.
+ //! Type of node can be determined by using type() function.
+ //! <br><br>
+ //! Note that after parse, both name and value of node, if any, will point interior of source text used for parsing.
+ //! Thus, this text must persist in the memory for the lifetime of node.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_node: public xml_base<Ch>
+ {
+
+ public:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Construction & destruction
+
+ //! Constructs an empty node with the specified type.
+ //! Consider using memory_pool of appropriate document to allocate nodes manually.
+ //! \param type Type of node to construct.
+ xml_node(node_type type)
+ : m_type(type)
+ , m_first_node(0)
+ , m_first_attribute(0)
+ {
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node data access
+
+ //! Gets type of node.
+ //! \return Type of node.
+ node_type type() const
+ {
+ return m_type;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Related nodes access
+
+ //! Gets document of which node is a child.
+ //! \return Pointer to document that contains this node, or 0 if there is no parent document.
+ xml_document<Ch> *document() const
+ {
+ xml_node<Ch> *node = const_cast<xml_node<Ch> *>(this);
+ while (node->parent())
+ node = node->parent();
+ return node->type() == node_document ? static_cast<xml_document<Ch> *>(node) : 0;
+ }
+
+ //! Gets first child node, optionally matching node name.
+ //! \param name Name of child to find, or 0 to return first child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found child, or 0 if not found.
+ xml_node<Ch> *first_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *child = m_first_node; child; child = child->next_sibling())
+ if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+ return child;
+ return 0;
+ }
+ else
+ return m_first_node;
+ }
+
+ //! Gets last child node, optionally matching node name.
+ //! Behaviour is undefined if node has no children.
+ //! Use first_node() to test if node has children.
+ //! \param name Name of child to find, or 0 to return last child regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found child, or 0 if not found.
+ xml_node<Ch> *last_node(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(m_first_node); // Cannot query for last child if node has no children
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *child = m_last_node; child; child = child->previous_sibling())
+ if (internal::compare(child->name(), child->name_size(), name, name_size, case_sensitive))
+ return child;
+ return 0;
+ }
+ else
+ return m_last_node;
+ }
+
+ //! Gets previous sibling node, optionally matching node name.
+ //! Behaviour is undefined if node has no parent.
+ //! Use parent() to test if node has a parent.
+ //! \param name Name of sibling to find, or 0 to return previous sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found sibling, or 0 if not found.
+ xml_node<Ch> *previous_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(this->m_parent); // Cannot query for siblings if node has no parent
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *sibling = m_prev_sibling; sibling; sibling = sibling->m_prev_sibling)
+ if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+ return sibling;
+ return 0;
+ }
+ else
+ return m_prev_sibling;
+ }
+
+ //! Gets next sibling node, optionally matching node name.
+ //! Behaviour is undefined if node has no parent.
+ //! Use parent() to test if node has a parent.
+ //! \param name Name of sibling to find, or 0 to return next sibling regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found sibling, or 0 if not found.
+ xml_node<Ch> *next_sibling(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ assert(this->m_parent); // Cannot query for siblings if node has no parent
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_node<Ch> *sibling = m_next_sibling; sibling; sibling = sibling->m_next_sibling)
+ if (internal::compare(sibling->name(), sibling->name_size(), name, name_size, case_sensitive))
+ return sibling;
+ return 0;
+ }
+ else
+ return m_next_sibling;
+ }
+
+ //! Gets first attribute of node, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return first attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *first_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_first_attribute; attribute; attribute = attribute->m_next_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return m_first_attribute;
+ }
+
+ //! Gets last attribute of node, optionally matching attribute name.
+ //! \param name Name of attribute to find, or 0 to return last attribute regardless of its name; this string doesn't have to be zero-terminated if name_size is non-zero
+ //! \param name_size Size of name, in characters, or 0 to have size calculated automatically from string
+ //! \param case_sensitive Should name comparison be case-sensitive; non case-sensitive comparison works properly only for ASCII characters
+ //! \return Pointer to found attribute, or 0 if not found.
+ xml_attribute<Ch> *last_attribute(const Ch *name = 0, std::size_t name_size = 0, bool case_sensitive = true) const
+ {
+ if (name)
+ {
+ if (name_size == 0)
+ name_size = internal::measure(name);
+ for (xml_attribute<Ch> *attribute = m_last_attribute; attribute; attribute = attribute->m_prev_attribute)
+ if (internal::compare(attribute->name(), attribute->name_size(), name, name_size, case_sensitive))
+ return attribute;
+ return 0;
+ }
+ else
+ return m_first_attribute ? m_last_attribute : 0;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node modification
+
+ //! Sets type of node.
+ //! \param type Type of node to set.
+ void type(node_type type)
+ {
+ m_type = type;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Node manipulation
+
+ //! Prepends a new child node.
+ //! The prepended child becomes the first child, and all existing children are moved one position back.
+ //! \param child Node to prepend.
+ void prepend_node(xml_node<Ch> *child)
+ {
+ assert(child && !child->parent() && child->type() != node_document);
+ if (first_node())
+ {
+ child->m_next_sibling = m_first_node;
+ m_first_node->m_prev_sibling = child;
+ }
+ else
+ {
+ child->m_next_sibling = 0;
+ m_last_node = child;
+ }
+ m_first_node = child;
+ child->m_parent = this;
+ child->m_prev_sibling = 0;
+ }
+
+ //! Appends a new child node.
+ //! The appended child becomes the last child.
+ //! \param child Node to append.
+ void append_node(xml_node<Ch> *child)
+ {
+ assert(child && !child->parent() && child->type() != node_document);
+ if (first_node())
+ {
+ child->m_prev_sibling = m_last_node;
+ m_last_node->m_next_sibling = child;
+ }
+ else
+ {
+ child->m_prev_sibling = 0;
+ m_first_node = child;
+ }
+ m_last_node = child;
+ child->m_parent = this;
+ child->m_next_sibling = 0;
+ }
+
+ //! Inserts a new child node at specified place inside the node.
+ //! All children after and including the specified node are moved one position back.
+ //! \param where Place where to insert the child, or 0 to insert at the back.
+ //! \param child Node to insert.
+ void insert_node(xml_node<Ch> *where, xml_node<Ch> *child)
+ {
+ assert(!where || where->parent() == this);
+ assert(child && !child->parent() && child->type() != node_document);
+ if (where == m_first_node)
+ prepend_node(child);
+ else if (where == 0)
+ append_node(child);
+ else
+ {
+ child->m_prev_sibling = where->m_prev_sibling;
+ child->m_next_sibling = where;
+ where->m_prev_sibling->m_next_sibling = child;
+ where->m_prev_sibling = child;
+ child->m_parent = this;
+ }
+ }
+
+ //! Removes first child node.
+ //! If node has no children, behaviour is undefined.
+ //! Use first_node() to test if node has children.
+ void remove_first_node()
+ {
+ assert(first_node());
+ xml_node<Ch> *child = m_first_node;
+ m_first_node = child->m_next_sibling;
+ if (child->m_next_sibling)
+ child->m_next_sibling->m_prev_sibling = 0;
+ else
+ m_last_node = 0;
+ child->m_parent = 0;
+ }
+
+ //! Removes last child of the node.
+ //! If node has no children, behaviour is undefined.
+ //! Use first_node() to test if node has children.
+ void remove_last_node()
+ {
+ assert(first_node());
+ xml_node<Ch> *child = m_last_node;
+ if (child->m_prev_sibling)
+ {
+ m_last_node = child->m_prev_sibling;
+ child->m_prev_sibling->m_next_sibling = 0;
+ }
+ else
+ m_first_node = 0;
+ child->m_parent = 0;
+ }
+
+ //! Removes specified child from the node
+ // \param where Pointer to child to be removed.
+ void remove_node(xml_node<Ch> *where)
+ {
+ assert(where && where->parent() == this);
+ assert(first_node());
+ if (where == m_first_node)
+ remove_first_node();
+ else if (where == m_last_node)
+ remove_last_node();
+ else
+ {
+ where->m_prev_sibling->m_next_sibling = where->m_next_sibling;
+ where->m_next_sibling->m_prev_sibling = where->m_prev_sibling;
+ where->m_parent = 0;
+ }
+ }
+
+ //! Removes all child nodes (but not attributes).
+ void remove_all_nodes()
+ {
+ for (xml_node<Ch> *node = first_node(); node; node = node->m_next_sibling)
+ node->m_parent = 0;
+ m_first_node = 0;
+ }
+
+ //! Prepends a new attribute to the node.
+ //! \param attribute Attribute to prepend.
+ void prepend_attribute(xml_attribute<Ch> *attribute)
+ {
+ assert(attribute && !attribute->parent());
+ if (first_attribute())
+ {
+ attribute->m_next_attribute = m_first_attribute;
+ m_first_attribute->m_prev_attribute = attribute;
+ }
+ else
+ {
+ attribute->m_next_attribute = 0;
+ m_last_attribute = attribute;
+ }
+ m_first_attribute = attribute;
+ attribute->m_parent = this;
+ attribute->m_prev_attribute = 0;
+ }
+
+ //! Appends a new attribute to the node.
+ //! \param attribute Attribute to append.
+ void append_attribute(xml_attribute<Ch> *attribute)
+ {
+ assert(attribute && !attribute->parent());
+ if (first_attribute())
+ {
+ attribute->m_prev_attribute = m_last_attribute;
+ m_last_attribute->m_next_attribute = attribute;
+ }
+ else
+ {
+ attribute->m_prev_attribute = 0;
+ m_first_attribute = attribute;
+ }
+ m_last_attribute = attribute;
+ attribute->m_parent = this;
+ attribute->m_next_attribute = 0;
+ }
+
+ //! Inserts a new attribute at specified place inside the node.
+ //! All attributes after and including the specified attribute are moved one position back.
+ //! \param where Place where to insert the attribute, or 0 to insert at the back.
+ //! \param attribute Attribute to insert.
+ void insert_attribute(xml_attribute<Ch> *where, xml_attribute<Ch> *attribute)
+ {
+ assert(!where || where->parent() == this);
+ assert(attribute && !attribute->parent());
+ if (where == m_first_attribute)
+ prepend_attribute(attribute);
+ else if (where == 0)
+ append_attribute(attribute);
+ else
+ {
+ attribute->m_prev_attribute = where->m_prev_attribute;
+ attribute->m_next_attribute = where;
+ where->m_prev_attribute->m_next_attribute = attribute;
+ where->m_prev_attribute = attribute;
+ attribute->m_parent = this;
+ }
+ }
+
+ //! Removes first attribute of the node.
+ //! If node has no attributes, behaviour is undefined.
+ //! Use first_attribute() to test if node has attributes.
+ void remove_first_attribute()
+ {
+ assert(first_attribute());
+ xml_attribute<Ch> *attribute = m_first_attribute;
+ if (attribute->m_next_attribute)
+ {
+ attribute->m_next_attribute->m_prev_attribute = 0;
+ }
+ else
+ m_last_attribute = 0;
+ attribute->m_parent = 0;
+ m_first_attribute = attribute->m_next_attribute;
+ }
+
+ //! Removes last attribute of the node.
+ //! If node has no attributes, behaviour is undefined.
+ //! Use first_attribute() to test if node has attributes.
+ void remove_last_attribute()
+ {
+ assert(first_attribute());
+ xml_attribute<Ch> *attribute = m_last_attribute;
+ if (attribute->m_prev_attribute)
+ {
+ attribute->m_prev_attribute->m_next_attribute = 0;
+ m_last_attribute = attribute->m_prev_attribute;
+ }
+ else
+ m_first_attribute = 0;
+ attribute->m_parent = 0;
+ }
+
+ //! Removes specified attribute from node.
+ //! \param where Pointer to attribute to be removed.
+ void remove_attribute(xml_attribute<Ch> *where)
+ {
+ assert(first_attribute() && where->parent() == this);
+ if (where == m_first_attribute)
+ remove_first_attribute();
+ else if (where == m_last_attribute)
+ remove_last_attribute();
+ else
+ {
+ where->m_prev_attribute->m_next_attribute = where->m_next_attribute;
+ where->m_next_attribute->m_prev_attribute = where->m_prev_attribute;
+ where->m_parent = 0;
+ }
+ }
+
+ //! Removes all attributes of node.
+ void remove_all_attributes()
+ {
+ for (xml_attribute<Ch> *attribute = first_attribute(); attribute; attribute = attribute->m_next_attribute)
+ attribute->m_parent = 0;
+ m_first_attribute = 0;
+ }
+
+ private:
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Restrictions
+
+ // No copying
+ xml_node(const xml_node &);
+ void operator =(const xml_node &);
+
+ ///////////////////////////////////////////////////////////////////////////
+ // Data members
+
+ // Note that some of the pointers below have UNDEFINED values if certain other pointers are 0.
+ // This is required for maximum performance, as it allows the parser to omit initialization of
+ // unneded/redundant values.
+ //
+ // The rules are as follows:
+ // 1. first_node and first_attribute contain valid pointers, or 0 if node has no children/attributes respectively
+ // 2. last_node and last_attribute are valid only if node has at least one child/attribute respectively, otherwise they contain garbage
+ // 3. prev_sibling and next_sibling are valid only if node has a parent, otherwise they contain garbage
+
+ node_type m_type; // Type of node; always valid
+ xml_node<Ch> *m_first_node; // Pointer to first child node, or 0 if none; always valid
+ xml_node<Ch> *m_last_node; // Pointer to last child node, or 0 if none; this value is only valid if m_first_node is non-zero
+ xml_attribute<Ch> *m_first_attribute; // Pointer to first attribute of node, or 0 if none; always valid
+ xml_attribute<Ch> *m_last_attribute; // Pointer to last attribute of node, or 0 if none; this value is only valid if m_first_attribute is non-zero
+ xml_node<Ch> *m_prev_sibling; // Pointer to previous sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+ xml_node<Ch> *m_next_sibling; // Pointer to next sibling of node, or 0 if none; this value is only valid if m_parent is non-zero
+
+ };
+
+ ///////////////////////////////////////////////////////////////////////////
+ // XML document
+
+ //! This class represents root of the DOM hierarchy.
+ //! It is also an xml_node and a memory_pool through public inheritance.
+ //! Use parse() function to build a DOM tree from a zero-terminated XML text string.
+ //! parse() function allocates memory for nodes and attributes by using functions of xml_document,
+ //! which are inherited from memory_pool.
+ //! To access root node of the document, use the document itself, as if it was an xml_node.
+ //! \param Ch Character type to use.
+ template<class Ch = char>
+ class xml_document: public xml_node<Ch>, public memory_pool<Ch>
+ {
+
+ public:
+
+ //! Constructs empty XML document
+ xml_document()
+ : xml_node<Ch>(node_document)
+ {
+ }
+
+ //! Parses zero-terminated XML string according to given flags.
+ //! Passed string will be modified by the parser, unless rapidxml::parse_non_destructive flag is used.
+ //! The string must persist for the lifetime of the document.
+ //! In case of error, rapidxml::parse_error exception will be thrown.
+ //! <br><br>
+ //! If you want to parse contents of a file, you must first load the file into the memory, and pass pointer to its beginning.
+ //! Make sure that data is zero-terminated.
+ //! <br><br>
+ //! Document can be parsed into multiple times.
+ //! Each new call to parse removes previous nodes and attributes (if any), but does not clear memory pool.
+ //! \param text XML data to parse; pointer is non-const to denote fact that this data may be modified by the parser.
+ template<int Flags>
+ void parse(Ch *text)
+ {
+ assert(text);
+
+ // Remove current contents
+ this->remove_all_nodes();
+ this->remove_all_attributes();
+
+ // Parse BOM, if any
+ parse_bom<Flags>(text);
+
+ // Parse children
+ while (1)
+ {
+ // Skip whitespace before node
+ skip<whitespace_pred, Flags>(text);
+ if (*text == 0)
+ break;
+
+ // Parse and append new child
+ if (*text == Ch('<'))
+ {
+ ++text; // Skip '<'
+ if (xml_node<Ch> *node = parse_node<Flags>(text))
+ this->append_node(node);
+ }
+ else
+ RAPIDXML_PARSE_ERROR("expected <", text);
+ }
+
+ }
+
+ //! Clears the document by deleting all nodes and clearing the memory pool.
+ //! All nodes owned by document pool are destroyed.
+ void clear()
+ {
+ this->remove_all_nodes();
+ this->remove_all_attributes();
+ memory_pool<Ch>::clear();
+ }
+
+ private:
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal character utility functions
+
+ // Detect whitespace character
+ struct whitespace_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_whitespace[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect node name character
+ struct node_name_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_node_name[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect attribute name character
+ struct attribute_name_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_attribute_name[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA)
+ struct text_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA) that does not require processing
+ struct text_pure_no_ws_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text_pure_no_ws[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect text character (PCDATA) that does not require processing
+ struct text_pure_with_ws_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ return internal::lookup_tables<0>::lookup_text_pure_with_ws[static_cast<unsigned char>(ch)];
+ }
+ };
+
+ // Detect attribute value character
+ template<Ch Quote>
+ struct attribute_value_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ if (Quote == Ch('\''))
+ return internal::lookup_tables<0>::lookup_attribute_data_1[static_cast<unsigned char>(ch)];
+ if (Quote == Ch('\"'))
+ return internal::lookup_tables<0>::lookup_attribute_data_2[static_cast<unsigned char>(ch)];
+ return 0; // Should never be executed, to avoid warnings on Comeau
+ }
+ };
+
+ // Detect attribute value character
+ template<Ch Quote>
+ struct attribute_value_pure_pred
+ {
+ static unsigned char test(Ch ch)
+ {
+ if (Quote == Ch('\''))
+ return internal::lookup_tables<0>::lookup_attribute_data_1_pure[static_cast<unsigned char>(ch)];
+ if (Quote == Ch('\"'))
+ return internal::lookup_tables<0>::lookup_attribute_data_2_pure[static_cast<unsigned char>(ch)];
+ return 0; // Should never be executed, to avoid warnings on Comeau
+ }
+ };
+
+ // Insert coded character, using UTF8 or 8-bit ASCII
+ template<int Flags>
+ static void insert_coded_character(Ch *&text, unsigned long code)
+ {
+ if (Flags & parse_no_utf8)
+ {
+ // Insert 8-bit ASCII character
+ // Todo: possibly verify that code is less than 256 and use replacement char otherwise?
+ text[0] = static_cast<unsigned char>(code);
+ text += 1;
+ }
+ else
+ {
+ // Insert UTF8 sequence
+ if (code < 0x80) // 1 byte sequence
+ {
+ text[0] = static_cast<unsigned char>(code);
+ text += 1;
+ }
+ else if (code < 0x800) // 2 byte sequence
+ {
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xC0);
+ text += 2;
+ }
+ else if (code < 0x10000) // 3 byte sequence
+ {
+ text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xE0);
+ text += 3;
+ }
+ else if (code < 0x110000) // 4 byte sequence
+ {
+ text[3] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[2] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[1] = static_cast<unsigned char>((code | 0x80) & 0xBF); code >>= 6;
+ text[0] = static_cast<unsigned char>(code | 0xF0);
+ text += 4;
+ }
+ else // Invalid, only codes up to 0x10FFFF are allowed in Unicode
+ {
+ RAPIDXML_PARSE_ERROR("invalid numeric character entity", text);
+ }
+ }
+ }
+
+ // Skip characters until predicate evaluates to true
+ template<class StopPred, int Flags>
+ static void skip(Ch *&text)
+ {
+ Ch *tmp = text;
+ while (StopPred::test(*tmp))
+ ++tmp;
+ text = tmp;
+ }
+
+ // Skip characters until predicate evaluates to true while doing the following:
+ // - replacing XML character entity references with proper characters (&apos; &amp; &quot; &lt; &gt; &#...;)
+ // - condensing whitespace sequences to single space character
+ template<class StopPred, class StopPredPure, int Flags>
+ static Ch *skip_and_expand_character_refs(Ch *&text)
+ {
+ // If entity translation, whitespace condense and whitespace trimming is disabled, use plain skip
+ if (Flags & parse_no_entity_translation &&
+ !(Flags & parse_normalize_whitespace) &&
+ !(Flags & parse_trim_whitespace))
+ {
+ skip<StopPred, Flags>(text);
+ return text;
+ }
+
+ // Use simple skip until first modification is detected
+ skip<StopPredPure, Flags>(text);
+
+ // Use translation skip
+ Ch *src = text;
+ Ch *dest = src;
+ while (StopPred::test(*src))
+ {
+ // If entity translation is enabled
+ if (!(Flags & parse_no_entity_translation))
+ {
+ // Test if replacement is needed
+ if (src[0] == Ch('&'))
+ {
+ switch (src[1])
+ {
+
+ // &amp; &apos;
+ case Ch('a'):
+ if (src[2] == Ch('m') && src[3] == Ch('p') && src[4] == Ch(';'))
+ {
+ *dest = Ch('&');
+ ++dest;
+ src += 5;
+ continue;
+ }
+ if (src[2] == Ch('p') && src[3] == Ch('o') && src[4] == Ch('s') && src[5] == Ch(';'))
+ {
+ *dest = Ch('\'');
+ ++dest;
+ src += 6;
+ continue;
+ }
+ break;
+
+ // &quot;
+ case Ch('q'):
+ if (src[2] == Ch('u') && src[3] == Ch('o') && src[4] == Ch('t') && src[5] == Ch(';'))
+ {
+ *dest = Ch('"');
+ ++dest;
+ src += 6;
+ continue;
+ }
+ break;
+
+ // &gt;
+ case Ch('g'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('>');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // &lt;
+ case Ch('l'):
+ if (src[2] == Ch('t') && src[3] == Ch(';'))
+ {
+ *dest = Ch('<');
+ ++dest;
+ src += 4;
+ continue;
+ }
+ break;
+
+ // &#...; - assumes ASCII
+ case Ch('#'):
+ if (src[2] == Ch('x'))
+ {
+ unsigned long code = 0;
+ src += 3; // Skip &#x
+ while (1)
+ {
+ unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+ if (digit == 0xFF)
+ break;
+ code = code * 16 + digit;
+ ++src;
+ }
+ insert_coded_character<Flags>(dest, code); // Put character in output
+ }
+ else
+ {
+ unsigned long code = 0;
+ src += 2; // Skip &#
+ while (1)
+ {
+ unsigned char digit = internal::lookup_tables<0>::lookup_digits[static_cast<unsigned char>(*src)];
+ if (digit == 0xFF)
+ break;
+ code = code * 10 + digit;
+ ++src;
+ }
+ insert_coded_character<Flags>(dest, code); // Put character in output
+ }
+ if (*src == Ch(';'))
+ ++src;
+ else
+ RAPIDXML_PARSE_ERROR("expected ;", src);
+ continue;
+
+ // Something else
+ default:
+ // Ignore, just copy '&' verbatim
+ break;
+
+ }
+ }
+ }
+
+ // If whitespace condensing is enabled
+ if (Flags & parse_normalize_whitespace)
+ {
+ // Test if condensing is needed
+ if (whitespace_pred::test(*src))
+ {
+ *dest = Ch(' '); ++dest; // Put single space in dest
+ ++src; // Skip first whitespace char
+ // Skip remaining whitespace chars
+ while (whitespace_pred::test(*src))
+ ++src;
+ continue;
+ }
+ }
+
+ // No replacement, only copy character
+ *dest++ = *src++;
+
+ }
+
+ // Return new end
+ text = src;
+ return dest;
+
+ }
+
+ ///////////////////////////////////////////////////////////////////////
+ // Internal parsing functions
+
+ // Parse BOM, if any
+ template<int Flags>
+ void parse_bom(Ch *&text)
+ {
+ // UTF-8?
+ if (static_cast<unsigned char>(text[0]) == 0xEF &&
+ static_cast<unsigned char>(text[1]) == 0xBB &&
+ static_cast<unsigned char>(text[2]) == 0xBF)
+ {
+ text += 3; // Skup utf-8 bom
+ }
+ }
+
+ // Parse XML declaration (<?xml...)
+ template<int Flags>
+ xml_node<Ch> *parse_xml_declaration(Ch *&text)
+ {
+ // If parsing of declaration is disabled
+ if (!(Flags & parse_declaration_node))
+ {
+ // Skip until end of declaration
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (!text[0]) {
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+ }
+ ++text;
+ }
+ text += 2; // Skip '?>'
+ return 0;
+ }
+
+ // Create declaration
+ xml_node<Ch> *declaration = this->allocate_node(node_declaration);
+
+ // Skip whitespace before attributes or ?>
+ skip<whitespace_pred, Flags>(text);
+
+ // Parse declaration attributes
+ parse_node_attributes<Flags>(text, declaration);
+
+ // Skip ?>
+ if (text[0] != Ch('?') || text[1] != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected ?>", text);
+ text += 2;
+
+ return declaration;
+ }
+
+ // Parse XML comment (<!--...)
+ template<int Flags>
+ xml_node<Ch> *parse_comment(Ch *&text)
+ {
+ // If parsing of comments is disabled
+ if (!(Flags & parse_comment_nodes))
+ {
+ // Skip until end of comment
+ while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+ {
+ if (!text[0]) {
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+ }
+ ++text;
+ }
+ text += 3; // Skip '-->'
+ return 0; // Do not produce comment node
+ }
+
+ // Remember value start
+ Ch *value = text;
+
+ // Skip until end of comment
+ while (text[0] != Ch('-') || text[1] != Ch('-') || text[2] != Ch('>'))
+ {
+ if (!text[0]) {
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+ }
+ ++text;
+ }
+
+ // Create comment node
+ xml_node<Ch> *comment = this->allocate_node(node_comment);
+ comment->value(value, text - value);
+
+ // Place zero terminator after comment value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 3; // Skip '-->'
+ return comment;
+ }
+
+ // Parse DOCTYPE
+ template<int Flags>
+ xml_node<Ch> *parse_doctype(Ch *&text)
+ {
+ // Remember value start
+ Ch *value = text;
+
+ // Skip to >
+ while (*text != Ch('>'))
+ {
+ // Determine character type
+ switch (*text)
+ {
+
+ // If '[' encountered, scan for matching ending ']' using naive algorithm with depth
+ // This works for all W3C test files except for 2 most wicked
+ case Ch('['):
+ {
+ ++text; // Skip '['
+ int depth = 1;
+ while (depth > 0)
+ {
+ switch (*text)
+ {
+ case Ch('['): ++depth; break;
+ case Ch(']'): --depth; break;
+ case 0: RAPIDXML_PARSE_ERROR("unexpected end of data", text); return 0;
+ }
+ ++text;
+ }
+ break;
+ }
+
+ // Error on end of text
+ case Ch('\0'):
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+
+ // Other character, skip it
+ default:
+ ++text;
+
+ }
+ }
+
+ // If DOCTYPE nodes enabled
+ if (Flags & parse_doctype_node)
+ {
+ // Create a new doctype node
+ xml_node<Ch> *doctype = this->allocate_node(node_doctype);
+ doctype->value(value, text - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 1; // skip '>'
+ return doctype;
+ }
+ else
+ {
+ text += 1; // skip '>'
+ return 0;
+ }
+
+ }
+
+ // Parse PI
+ template<int Flags>
+ xml_node<Ch> *parse_pi(Ch *&text)
+ {
+ // If creation of PI nodes is enabled
+ if (Flags & parse_pi_nodes)
+ {
+ // Create pi node
+ xml_node<Ch> *pi = this->allocate_node(node_pi);
+
+ // Extract PI target name
+ Ch *name = text;
+ skip<node_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected PI target", text);
+ pi->name(name, text - name);
+
+ // Skip whitespace between pi target and pi
+ skip<whitespace_pred, Flags>(text);
+
+ // Remember start of pi
+ Ch *value = text;
+
+ // Skip to '?>'
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (*text == Ch('\0')) {
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+ }
+ ++text;
+ }
+
+ // Set pi value (verbatim, no entity expansion or whitespace normalization)
+ pi->value(value, text - value);
+
+ // Place zero terminator after name and value
+ if (!(Flags & parse_no_string_terminators))
+ {
+ pi->name()[pi->name_size()] = Ch('\0');
+ pi->value()[pi->value_size()] = Ch('\0');
+ }
+
+ text += 2; // Skip '?>'
+ return pi;
+ }
+ else
+ {
+ // Skip to '?>'
+ while (text[0] != Ch('?') || text[1] != Ch('>'))
+ {
+ if (*text == Ch('\0')) {
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+ }
+ ++text;
+ }
+ text += 2; // Skip '?>'
+ return 0;
+ }
+ }
+
+ // Parse and append data
+ // Return character that ends data.
+ // This is necessary because this character might have been overwritten by a terminating 0
+ template<int Flags>
+ Ch parse_and_append_data(xml_node<Ch> *node, Ch *&text, Ch *contents_start)
+ {
+ // Backup to contents start if whitespace trimming is disabled
+ if (!(Flags & parse_trim_whitespace))
+ text = contents_start;
+
+ // Skip until end of data
+ Ch *value = text, *end;
+ if (Flags & parse_normalize_whitespace)
+ end = skip_and_expand_character_refs<text_pred, text_pure_with_ws_pred, Flags>(text);
+ else
+ end = skip_and_expand_character_refs<text_pred, text_pure_no_ws_pred, Flags>(text);
+
+ // Trim trailing whitespace if flag is set; leading was already trimmed by whitespace skip after >
+ if (Flags & parse_trim_whitespace)
+ {
+ if (Flags & parse_normalize_whitespace)
+ {
+ // Whitespace is already condensed to single space characters by skipping function, so just trim 1 char off the end
+ if (*(end - 1) == Ch(' '))
+ --end;
+ }
+ else
+ {
+ // Backup until non-whitespace character is found
+ while (whitespace_pred::test(*(end - 1)))
+ --end;
+ }
+ }
+
+ // If characters are still left between end and value (this test is only necessary if normalization is enabled)
+ // Create new data node
+ if (!(Flags & parse_no_data_nodes))
+ {
+ xml_node<Ch> *data = this->allocate_node(node_data);
+ data->value(value, end - value);
+ node->append_node(data);
+ }
+
+ // Add data to parent node if no data exists yet
+ if (!(Flags & parse_no_element_values))
+ if (*node->value() == Ch('\0'))
+ node->value(value, end - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ {
+ Ch ch = *text;
+ *end = Ch('\0');
+ return ch; // Return character that ends data; this is required because zero terminator overwritten it
+ }
+
+ // Return character that ends data
+ return *text;
+ }
+
+ // Parse CDATA
+ template<int Flags>
+ xml_node<Ch> *parse_cdata(Ch *&text)
+ {
+ // If CDATA is disabled
+ if (Flags & parse_no_data_nodes)
+ {
+ // Skip until end of cdata
+ while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+ {
+ if (!text[0]) {
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+ }
+ ++text;
+ }
+ text += 3; // Skip ]]>
+ return 0; // Do not produce CDATA node
+ }
+
+ // Skip until end of cdata
+ Ch *value = text;
+ while (text[0] != Ch(']') || text[1] != Ch(']') || text[2] != Ch('>'))
+ {
+ if (!text[0]) {
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+ }
+ ++text;
+ }
+
+ // Create new cdata node
+ xml_node<Ch> *cdata = this->allocate_node(node_cdata);
+ cdata->value(value, text - value);
+
+ // Place zero terminator after value
+ if (!(Flags & parse_no_string_terminators))
+ *text = Ch('\0');
+
+ text += 3; // Skip ]]>
+ return cdata;
+ }
+
+ // Parse element node
+ template<int Flags>
+ xml_node<Ch> *parse_element(Ch *&text)
+ {
+ // Create element node
+ xml_node<Ch> *element = this->allocate_node(node_element);
+
+ // Extract element name
+ Ch *name = text;
+ skip<node_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected element name", text);
+ element->name(name, text - name);
+
+ // Skip whitespace between element name and attributes or >
+ skip<whitespace_pred, Flags>(text);
+
+ // Parse attributes, if any
+ parse_node_attributes<Flags>(text, element);
+
+ // Determine ending type
+ if (*text == Ch('>'))
+ {
+ ++text;
+ parse_node_contents<Flags>(text, element);
+ }
+ else if (*text == Ch('/'))
+ {
+ ++text;
+ if (*text != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected >", text);
+ ++text;
+ }
+ else
+ RAPIDXML_PARSE_ERROR("expected >", text);
+
+ // Place zero terminator after name
+ if (!(Flags & parse_no_string_terminators))
+ element->name()[element->name_size()] = Ch('\0');
+
+ // Return parsed element
+ return element;
+ }
+
+ // Determine node type, and parse it
+ template<int Flags>
+ xml_node<Ch> *parse_node(Ch *&text)
+ {
+ // Parse proper node type
+ switch (text[0])
+ {
+
+ // <...
+ default:
+ // Parse and append element node
+ return parse_element<Flags>(text);
+
+ // <?...
+ case Ch('?'):
+ ++text; // Skip ?
+ if ((text[0] == Ch('x') || text[0] == Ch('X')) &&
+ (text[1] == Ch('m') || text[1] == Ch('M')) &&
+ (text[2] == Ch('l') || text[2] == Ch('L')) &&
+ whitespace_pred::test(text[3]))
+ {
+ // '<?xml ' - xml declaration
+ text += 4; // Skip 'xml '
+ return parse_xml_declaration<Flags>(text);
+ }
+ else
+ {
+ // Parse PI
+ return parse_pi<Flags>(text);
+ }
+
+ // <!...
+ case Ch('!'):
+
+ // Parse proper subset of <! node
+ switch (text[1])
+ {
+
+ // <!-
+ case Ch('-'):
+ if (text[2] == Ch('-'))
+ {
+ // '<!--' - xml comment
+ text += 3; // Skip '!--'
+ return parse_comment<Flags>(text);
+ }
+ break;
+
+ // <![
+ case Ch('['):
+ if (text[2] == Ch('C') && text[3] == Ch('D') && text[4] == Ch('A') &&
+ text[5] == Ch('T') && text[6] == Ch('A') && text[7] == Ch('['))
+ {
+ // '<![CDATA[' - cdata
+ text += 8; // Skip '![CDATA['
+ return parse_cdata<Flags>(text);
+ }
+ break;
+
+ // <!D
+ case Ch('D'):
+ if (text[2] == Ch('O') && text[3] == Ch('C') && text[4] == Ch('T') &&
+ text[5] == Ch('Y') && text[6] == Ch('P') && text[7] == Ch('E') &&
+ whitespace_pred::test(text[8]))
+ {
+ // '<!DOCTYPE ' - doctype
+ text += 9; // skip '!DOCTYPE '
+ return parse_doctype<Flags>(text);
+ }
+
+ } // switch
+
+ // Attempt to skip other, unrecognized node types starting with <!
+ ++text; // Skip !
+ while (*text != Ch('>'))
+ {
+ if (*text == 0) {
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return 0;
+ }
+ ++text;
+ }
+ ++text; // Skip '>'
+ return 0; // No node recognized
+
+ }
+ }
+
+ // Parse contents of the node - children, data etc.
+ template<int Flags>
+ void parse_node_contents(Ch *&text, xml_node<Ch> *node)
+ {
+ // For all children and text
+ while (1)
+ {
+ // Skip whitespace between > and node contents
+ Ch *contents_start = text; // Store start of node contents before whitespace is skipped
+ skip<whitespace_pred, Flags>(text);
+ Ch next_char = *text;
+
+ // After data nodes, instead of continuing the loop, control jumps here.
+ // This is because zero termination inside parse_and_append_data() function
+ // would wreak havoc with the above code.
+ // Also, skipping whitespace after data nodes is unnecessary.
+ after_data_node:
+
+ // Determine what comes next: node closing, child node, data node, or 0?
+ switch (next_char)
+ {
+
+ // Node closing or child node
+ case Ch('<'):
+ if (text[1] == Ch('/'))
+ {
+ // Node closing
+ text += 2; // Skip '</'
+ if (Flags & parse_validate_closing_tags)
+ {
+ // Skip and validate closing tag name
+ Ch *closing_name = text;
+ skip<node_name_pred, Flags>(text);
+ if (!internal::compare(node->name(), node->name_size(), closing_name, text - closing_name, true))
+ RAPIDXML_PARSE_ERROR("invalid closing tag name", text);
+ }
+ else
+ {
+ // No validation, just skip name
+ skip<node_name_pred, Flags>(text);
+ }
+ // Skip remaining whitespace after node name
+ skip<whitespace_pred, Flags>(text);
+ if (*text != Ch('>'))
+ RAPIDXML_PARSE_ERROR("expected >", text);
+ ++text; // Skip '>'
+ return; // Node closed, finished parsing contents
+ }
+ else
+ {
+ // Child node
+ ++text; // Skip '<'
+ if (xml_node<Ch> *child = parse_node<Flags>(text))
+ node->append_node(child);
+ }
+ break;
+
+ // End of data - error
+ case Ch('\0'):
+ RAPIDXML_PARSE_ERROR("unexpected end of data", text);
+ return;
+
+ // Data node
+ default:
+ next_char = parse_and_append_data<Flags>(node, text, contents_start);
+ goto after_data_node; // Bypass regular processing after data nodes
+
+ }
+ }
+ }
+
+ // Parse XML attributes of the node
+ template<int Flags>
+ void parse_node_attributes(Ch *&text, xml_node<Ch> *node)
+ {
+ // For all attributes
+ while (attribute_name_pred::test(*text))
+ {
+ // Extract attribute name
+ Ch *name = text;
+ ++text; // Skip first character of attribute name
+ skip<attribute_name_pred, Flags>(text);
+ if (text == name)
+ RAPIDXML_PARSE_ERROR("expected attribute name", name);
+
+ // Create new attribute
+ xml_attribute<Ch> *attribute = this->allocate_attribute();
+ attribute->name(name, text - name);
+ node->append_attribute(attribute);
+
+ // Skip whitespace after attribute name
+ skip<whitespace_pred, Flags>(text);
+
+ // Skip =
+ if (*text != Ch('='))
+ RAPIDXML_PARSE_ERROR("expected =", text);
+ ++text;
+
+ // Add terminating zero after name
+ if (!(Flags & parse_no_string_terminators))
+ attribute->name()[attribute->name_size()] = 0;
+
+ // Skip whitespace after =
+ skip<whitespace_pred, Flags>(text);
+
+ // Skip quote and remember if it was ' or "
+ Ch quote = *text;
+ if (quote != Ch('\'') && quote != Ch('"'))
+ RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+ ++text;
+
+ // Extract attribute value and expand char refs in it
+ Ch *value = text, *end;
+ const int AttFlags = Flags & ~parse_normalize_whitespace; // No whitespace normalization in attributes
+ if (quote == Ch('\''))
+ end = skip_and_expand_character_refs<attribute_value_pred<Ch('\'')>, attribute_value_pure_pred<Ch('\'')>, AttFlags>(text);
+ else
+ end = skip_and_expand_character_refs<attribute_value_pred<Ch('"')>, attribute_value_pure_pred<Ch('"')>, AttFlags>(text);
+
+ // Set attribute value
+ attribute->value(value, end - value);
+
+ // Make sure that end quote is present
+ if (*text != quote)
+ RAPIDXML_PARSE_ERROR("expected ' or \"", text);
+ ++text; // Skip quote
+
+ // Add terminating zero after value
+ if (!(Flags & parse_no_string_terminators))
+ attribute->value()[attribute->value_size()] = 0;
+
+ // Skip whitespace after attribute value
+ skip<whitespace_pred, Flags>(text);
+ }
+ }
+
+ };
+
+ //! \cond internal
+ namespace internal
+ {
+
+ // Whitespace (space \n \r \t)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_whitespace[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, // 0
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 1
+ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 2
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 3
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 4
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 5
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 6
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 7
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 8
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 9
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // A
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // B
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // C
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // D
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // E
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 // F
+ };
+
+ // Node name (anything but space \n \r \t / > ? \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_node_name[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) (anything but < \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) that does not require processing when ws normalization is disabled
+ // (anything but < \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text_pure_no_ws[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Text (i.e. PCDATA) that does not require processing when ws normalizationis is enabled
+ // (anything but < \0 & space \n \r \t)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_text_pure_with_ws[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute name (anything but space \n \r \t / < > = ? ! \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_name[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with single quote (anything but ' \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with single quote that does not require processing (anything but ' \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_1_pure[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with double quote (anything but " \0)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Attribute data with double quote that does not require processing (anything but " \0 &)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_attribute_data_2_pure[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 0
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 1
+ 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 2
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 3
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 4
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 5
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 6
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 7
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 8
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // 9
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // A
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // B
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // C
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // D
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, // E
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // F
+ };
+
+ // Digits (dec and hex, 255 denotes end of numeric character reference)
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_digits[256] =
+ {
+ // 0 1 2 3 4 5 6 7 8 9 A B C D E F
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 0
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 1
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 2
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,255,255,255,255,255,255, // 3
+ 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 4
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 5
+ 255, 10, 11, 12, 13, 14, 15,255,255,255,255,255,255,255,255,255, // 6
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 7
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 8
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // 9
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // A
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // B
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // C
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // D
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, // E
+ 255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255 // F
+ };
+
+ // Upper case conversion
+ template<int Dummy>
+ const unsigned char lookup_tables<Dummy>::lookup_upcase[256] =
+ {
+ // 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A B C D E F
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, // 0
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, // 1
+ 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, // 2
+ 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, // 3
+ 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 4
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, // 5
+ 96, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, // 6
+ 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 123,124,125,126,127, // 7
+ 128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, // 8
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, // 9
+ 160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175, // A
+ 176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, // B
+ 192,193,194,195,196,197,198,199,200,201,202,203,204,205,206,207, // C
+ 208,209,210,211,212,213,214,215,216,217,218,219,220,221,222,223, // D
+ 224,225,226,227,228,229,230,231,232,233,234,235,236,237,238,239, // E
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 // F
+ };
+ }
+ //! \endcond
+
+}
+
+// Undefine internal macros
+#undef RAPIDXML_PARSE_ERROR
+
+// On MSVC, restore warnings state
+#ifdef _MSC_VER
+ #pragma warning(pop)
+#endif
+
+#endif
diff --git a/gui/remaining.txt b/gui/remaining.txt
new file mode 100644
index 000000000..298ee90ad
--- /dev/null
+++ b/gui/remaining.txt
@@ -0,0 +1,4 @@
+* Confirmation of action
+* Multi-String Variables
+* String Box
+
diff --git a/gui/resources.cpp b/gui/resources.cpp
new file mode 100644
index 000000000..41655c376
--- /dev/null
+++ b/gui/resources.cpp
@@ -0,0 +1,377 @@
+// resource.cpp - Source to manage GUI resources
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <string>
+#include <sstream>
+#include <iostream>
+#include <iomanip>
+
+#include "../minzip/Zip.h"
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+#include "gui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+#define TMP_RESOURCE_NAME "/tmp/extract.bin"
+
+Resource::Resource(xml_node<>* node, ZipArchive* pZip)
+{
+ if (node && node->first_attribute("name"))
+ mName = node->first_attribute("name")->value();
+}
+
+int Resource::ExtractResource(ZipArchive* pZip, std::string folderName, std::string fileName, std::string fileExtn, std::string destFile)
+{
+ if (!pZip)
+ return -1;
+
+ std::string src = folderName + "/" + fileName + fileExtn;
+
+ const ZipEntry* binary = mzFindZipEntry(pZip, src.c_str());
+ if (binary == NULL) {
+ return -1;
+ }
+
+ unlink(destFile.c_str());
+ int fd = creat(destFile.c_str(), 0666);
+ if (fd < 0)
+ return -1;
+
+ int ret = 0;
+ if (!mzExtractZipEntryToFile(pZip, binary, fd))
+ ret = -1;
+
+ close(fd);
+ return ret;
+}
+
+void Resource::LoadImage(ZipArchive* pZip, std::string file, gr_surface* source)
+{
+ if (ExtractResource(pZip, "images", file, ".png", TMP_RESOURCE_NAME) == 0)
+ {
+ res_create_surface(TMP_RESOURCE_NAME, source);
+ unlink(TMP_RESOURCE_NAME);
+ }
+ else if (ExtractResource(pZip, "images", file, "", TMP_RESOURCE_NAME) == 0)
+ {
+ // JPG includes the .jpg extension in the filename so extension should be blank
+ res_create_surface(TMP_RESOURCE_NAME, source);
+ unlink(TMP_RESOURCE_NAME);
+ }
+ else if (!pZip)
+ {
+ // File name in xml may have included .png so try without adding .png
+ res_create_surface(file.c_str(), source);
+ }
+}
+
+void Resource::CheckAndScaleImage(gr_surface source, gr_surface* destination, int retain_aspect)
+{
+ if (!source) {
+ *destination = NULL;
+ return;
+ }
+ if (get_scale_w() != 0 && get_scale_h() != 0) {
+ float scale_w = get_scale_w(), scale_h = get_scale_h();
+ if (retain_aspect) {
+ if (scale_w < scale_h)
+ scale_h = scale_w;
+ else
+ scale_w = scale_h;
+ }
+ if (res_scale_surface(source, destination, scale_w, scale_h)) {
+ LOGINFO("Error scaling image, using regular size.\n");
+ *destination = source;
+ }
+ } else {
+ *destination = source;
+ }
+}
+
+FontResource::FontResource(xml_node<>* node, ZipArchive* pZip)
+ : Resource(node, pZip)
+{
+ std::string file;
+ xml_attribute<>* attr;
+
+ mFont = NULL;
+ if (!node)
+ return;
+
+ attr = node->first_attribute("filename");
+ if (!attr)
+ return;
+
+ file = attr->value();
+
+#ifndef TW_DISABLE_TTF
+ if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
+ {
+ m_type = TYPE_TTF;
+
+ attr = node->first_attribute("size");
+ if(!attr)
+ return;
+
+ int size = scale_theme_min(atoi(attr->value()));
+ int dpi = 300;
+
+ attr = node->first_attribute("dpi");
+ if(attr)
+ dpi = atoi(attr->value());
+
+ if (ExtractResource(pZip, "fonts", file, "", TMP_RESOURCE_NAME) == 0)
+ {
+ mFont = gr_ttf_loadFont(TMP_RESOURCE_NAME, size, dpi);
+ unlink(TMP_RESOURCE_NAME);
+ }
+ else
+ {
+ file = std::string(TWRES "fonts/") + file;
+ mFont = gr_ttf_loadFont(file.c_str(), size, dpi);
+ }
+ }
+ else
+#endif
+ {
+ m_type = TYPE_TWRP;
+
+ if(file.size() >= 4 && file.compare(file.size()-4, 4, ".ttf") == 0)
+ {
+ attr = node->first_attribute("fallback");
+ if (!attr)
+ return;
+
+ file = attr->value();
+ }
+
+ if (ExtractResource(pZip, "fonts", file, ".dat", TMP_RESOURCE_NAME) == 0)
+ {
+ mFont = gr_loadFont(TMP_RESOURCE_NAME);
+ unlink(TMP_RESOURCE_NAME);
+ }
+ else
+ {
+ mFont = gr_loadFont(file.c_str());
+ }
+ }
+}
+
+FontResource::~FontResource()
+{
+ if(mFont)
+ {
+#ifndef TW_DISABLE_TTF
+ if(m_type == TYPE_TTF)
+ gr_ttf_freeFont(mFont);
+ else
+#endif
+ gr_freeFont(mFont);
+ }
+}
+
+ImageResource::ImageResource(xml_node<>* node, ZipArchive* pZip)
+ : Resource(node, pZip)
+{
+ std::string file;
+ gr_surface temp_surface = NULL;
+
+ mSurface = NULL;
+ if (!node) {
+ LOGERR("ImageResource node is NULL\n");
+ return;
+ }
+
+ if (node->first_attribute("filename"))
+ file = node->first_attribute("filename")->value();
+ else {
+ LOGERR("No filename specified for image resource.\n");
+ return;
+ }
+
+ bool retain_aspect = (node->first_attribute("retainaspect") != NULL);
+ // the value does not matter, if retainaspect is present, we assume that we want to retain it
+ LoadImage(pZip, file, &temp_surface);
+ CheckAndScaleImage(temp_surface, &mSurface, retain_aspect);
+}
+
+ImageResource::~ImageResource()
+{
+ if (mSurface)
+ res_free_surface(mSurface);
+}
+
+AnimationResource::AnimationResource(xml_node<>* node, ZipArchive* pZip)
+ : Resource(node, pZip)
+{
+ std::string file;
+ int fileNum = 1;
+
+ if (!node)
+ return;
+
+ if (node->first_attribute("filename"))
+ file = node->first_attribute("filename")->value();
+ else {
+ LOGERR("No filename specified for image resource.\n");
+ return;
+ }
+
+ bool retain_aspect = (node->first_attribute("retainaspect") != NULL);
+ // the value does not matter, if retainaspect is present, we assume that we want to retain it
+ for (;;)
+ {
+ std::ostringstream fileName;
+ fileName << file << std::setfill ('0') << std::setw (3) << fileNum;
+
+ gr_surface surface, temp_surface = NULL;
+ LoadImage(pZip, fileName.str(), &temp_surface);
+ CheckAndScaleImage(temp_surface, &surface, retain_aspect);
+ if (surface) {
+ mSurfaces.push_back(surface);
+ fileNum++;
+ } else
+ break; // Done loading animation images
+ }
+}
+
+AnimationResource::~AnimationResource()
+{
+ std::vector<gr_surface>::iterator it;
+
+ for (it = mSurfaces.begin(); it != mSurfaces.end(); ++it)
+ res_free_surface(*it);
+
+ mSurfaces.clear();
+}
+
+FontResource* ResourceManager::FindFont(const std::string& name) const
+{
+ for (std::vector<FontResource*>::const_iterator it = mFonts.begin(); it != mFonts.end(); ++it)
+ if (name == (*it)->GetName())
+ return *it;
+ return NULL;
+}
+
+ImageResource* ResourceManager::FindImage(const std::string& name) const
+{
+ for (std::vector<ImageResource*>::const_iterator it = mImages.begin(); it != mImages.end(); ++it)
+ if (name == (*it)->GetName())
+ return *it;
+ return NULL;
+}
+
+AnimationResource* ResourceManager::FindAnimation(const std::string& name) const
+{
+ for (std::vector<AnimationResource*>::const_iterator it = mAnimations.begin(); it != mAnimations.end(); ++it)
+ if (name == (*it)->GetName())
+ return *it;
+ return NULL;
+}
+
+std::string ResourceManager::FindString(const std::string& name) const
+{
+ std::map<std::string, std::string>::const_iterator it = mStrings.find(name);
+ if (it != mStrings.end())
+ return it->second;
+ return "[" + name + ("]");
+}
+
+ResourceManager::ResourceManager()
+{
+}
+
+void ResourceManager::LoadResources(xml_node<>* resList, ZipArchive* pZip)
+{
+ if (!resList)
+ return;
+
+ for (xml_node<>* child = resList->first_node(); child; child = child->next_sibling())
+ {
+ std::string type = child->name();
+ if (type == "resource") {
+ // legacy format : <resource type="...">
+ xml_attribute<>* attr = child->first_attribute("type");
+ type = attr ? attr->value() : "*unspecified*";
+ }
+
+ bool error = false;
+ if (type == "font")
+ {
+ FontResource* res = new FontResource(child, pZip);
+ if (res->GetResource())
+ mFonts.push_back(res);
+ else {
+ error = true;
+ delete res;
+ }
+ }
+ else if (type == "image")
+ {
+ ImageResource* res = new ImageResource(child, pZip);
+ if (res->GetResource())
+ mImages.push_back(res);
+ else {
+ error = true;
+ delete res;
+ }
+ }
+ else if (type == "animation")
+ {
+ AnimationResource* res = new AnimationResource(child, pZip);
+ if (res->GetResourceCount())
+ mAnimations.push_back(res);
+ else {
+ error = true;
+ delete res;
+ }
+ }
+ else if (type == "string")
+ {
+ if (xml_attribute<>* attr = child->first_attribute("name"))
+ mStrings[attr->value()] = child->value();
+ else
+ error = true;
+ }
+ else
+ {
+ LOGERR("Resource type (%s) not supported.\n", type.c_str());
+ error = true;
+ }
+
+ if (error)
+ {
+ std::string res_name;
+ if (child->first_attribute("name"))
+ res_name = child->first_attribute("name")->value();
+ if (res_name.empty() && child->first_attribute("filename"))
+ res_name = child->first_attribute("filename")->value();
+
+ if (!res_name.empty()) {
+ LOGERR("Resource (%s)-(%s) failed to load\n", type.c_str(), res_name.c_str());
+ } else
+ LOGERR("Resource type (%s) failed to load\n", type.c_str());
+ }
+ }
+}
+
+ResourceManager::~ResourceManager()
+{
+ for (std::vector<FontResource*>::iterator it = mFonts.begin(); it != mFonts.end(); ++it)
+ delete *it;
+
+ for (std::vector<ImageResource*>::iterator it = mImages.begin(); it != mImages.end(); ++it)
+ delete *it;
+
+ for (std::vector<AnimationResource*>::iterator it = mAnimations.begin(); it != mAnimations.end(); ++it)
+ delete *it;
+}
diff --git a/gui/resources.hpp b/gui/resources.hpp
new file mode 100644
index 000000000..0eb32674d
--- /dev/null
+++ b/gui/resources.hpp
@@ -0,0 +1,110 @@
+// resources.hpp - Base classes for resource management of GUI
+
+#ifndef _RESOURCE_HEADER
+#define _RESOURCE_HEADER
+
+#include <string>
+#include <vector>
+#include <map>
+
+struct ZipArchive;
+
+extern "C" {
+#include "../minuitwrp/minui.h"
+}
+
+// Base Objects
+class Resource
+{
+public:
+ Resource(xml_node<>* node, ZipArchive* pZip);
+ virtual ~Resource() {}
+
+public:
+ std::string GetName() { return mName; }
+
+private:
+ std::string mName;
+
+protected:
+ static int ExtractResource(ZipArchive* pZip, std::string folderName, std::string fileName, std::string fileExtn, std::string destFile);
+ static void LoadImage(ZipArchive* pZip, std::string file, gr_surface* source);
+ static void CheckAndScaleImage(gr_surface source, gr_surface* destination, int retain_aspect);
+};
+
+class FontResource : public Resource
+{
+public:
+ enum Type
+ {
+ TYPE_TWRP,
+#ifndef TW_DISABLE_TTF
+ TYPE_TTF,
+#endif
+ };
+
+ FontResource(xml_node<>* node, ZipArchive* pZip);
+ virtual ~FontResource();
+
+public:
+ void* GetResource() { return this ? mFont : NULL; }
+ int GetHeight() { return gr_getMaxFontHeight(this ? mFont : NULL); }
+
+protected:
+ void* mFont;
+ Type m_type;
+};
+
+class ImageResource : public Resource
+{
+public:
+ ImageResource(xml_node<>* node, ZipArchive* pZip);
+ virtual ~ImageResource();
+
+public:
+ gr_surface GetResource() { return this ? mSurface : NULL; }
+ int GetWidth() { return gr_get_width(this ? mSurface : NULL); }
+ int GetHeight() { return gr_get_height(this ? mSurface : NULL); }
+
+protected:
+ gr_surface mSurface;
+};
+
+class AnimationResource : public Resource
+{
+public:
+ AnimationResource(xml_node<>* node, ZipArchive* pZip);
+ virtual ~AnimationResource();
+
+public:
+ gr_surface GetResource() { return (!this || mSurfaces.empty()) ? NULL : mSurfaces.at(0); }
+ gr_surface GetResource(int entry) { return (!this || mSurfaces.empty()) ? NULL : mSurfaces.at(entry); }
+ int GetWidth() { return gr_get_width(this ? GetResource() : NULL); }
+ int GetHeight() { return gr_get_height(this ? GetResource() : NULL); }
+ int GetResourceCount() { return mSurfaces.size(); }
+
+protected:
+ std::vector<gr_surface> mSurfaces;
+};
+
+class ResourceManager
+{
+public:
+ ResourceManager();
+ virtual ~ResourceManager();
+ void LoadResources(xml_node<>* resList, ZipArchive* pZip);
+
+public:
+ FontResource* FindFont(const std::string& name) const;
+ ImageResource* FindImage(const std::string& name) const;
+ AnimationResource* FindAnimation(const std::string& name) const;
+ std::string FindString(const std::string& name) const;
+
+private:
+ std::vector<FontResource*> mFonts;
+ std::vector<ImageResource*> mImages;
+ std::vector<AnimationResource*> mAnimations;
+ std::map<std::string, std::string> mStrings;
+};
+
+#endif // _RESOURCE_HEADER
diff --git a/gui/scrolllist.cpp b/gui/scrolllist.cpp
new file mode 100644
index 000000000..ec42fe6c0
--- /dev/null
+++ b/gui/scrolllist.cpp
@@ -0,0 +1,609 @@
+/*
+ Copyright 2013 bigbiff/Dees_Troy TeamWin
+ This file is part of TWRP/TeamWin Recovery Project.
+
+ TWRP is free software: you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation, either version 3 of the License, or
+ (at your option) any later version.
+
+ TWRP is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with TWRP. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include <string.h>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../data.hpp"
+
+const float SCROLLING_SPEED_DECREMENT = 0.9; // friction
+const int SCROLLING_FLOOR = 2; // minimum pixels for scrolling to stop
+
+GUIScrollList::GUIScrollList(xml_node<>* node) : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ firstDisplayedItem = mItemSpacing = mFontHeight = mSeparatorH = y_offset = scrollingSpeed = 0;
+ maxIconWidth = maxIconHeight = mHeaderIconHeight = mHeaderIconWidth = 0;
+ mHeaderSeparatorH = mHeaderH = actualItemHeight = 0;
+ mHeaderIsStatic = false;
+ mBackground = mHeaderIcon = NULL;
+ mFont = NULL;
+ mFastScrollW = mFastScrollLineW = mFastScrollRectW = mFastScrollRectH = 0;
+ mFastScrollRectCurrentY = mFastScrollRectCurrentH = mFastScrollRectTouchY = 0;
+ lastY = last2Y = fastScroll = 0;
+ mUpdate = 0;
+ touchDebounce = 6;
+ ConvertStrToColor("black", &mBackgroundColor);
+ ConvertStrToColor("black", &mHeaderBackgroundColor);
+ ConvertStrToColor("black", &mSeparatorColor);
+ ConvertStrToColor("black", &mHeaderSeparatorColor);
+ ConvertStrToColor("white", &mFontColor);
+ ConvertStrToColor("white", &mHeaderFontColor);
+ ConvertStrToColor("white", &mFastScrollLineColor);
+ ConvertStrToColor("white", &mFastScrollRectColor);
+ hasHighlightColor = false;
+ allowSelection = true;
+ selectedItem = NO_ITEM;
+
+ // Load header text
+ // note: node can be NULL for the emergency console
+ child = node ? node->first_node("text") : NULL;
+ if (child) mHeaderText = child->value();
+ // Simple way to check for static state
+ mLastHeaderValue = gui_parse_text(mHeaderText);
+ mHeaderIsStatic = (mLastHeaderValue == mHeaderText);
+
+ mHighlightColor = LoadAttrColor(FindNode(node, "highlight"), "color", &hasHighlightColor);
+
+ child = FindNode(node, "background");
+ if (child)
+ {
+ mBackground = LoadAttrImage(child, "resource");
+ mBackgroundColor = LoadAttrColor(child, "color");
+ }
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
+ SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+
+ // Load the font, and possibly override the color
+ child = FindNode(node, "font");
+ if (child)
+ {
+ mFont = LoadAttrFont(child, "resource");
+ mFontColor = LoadAttrColor(child, "color");
+ mFontHighlightColor = LoadAttrColor(child, "highlightcolor", mFontColor);
+ mItemSpacing = LoadAttrIntScaleY(child, "spacing");
+ }
+
+ // Load the separator if it exists
+ child = FindNode(node, "separator");
+ if (child)
+ {
+ mSeparatorColor = LoadAttrColor(child, "color");
+ mSeparatorH = LoadAttrIntScaleY(child, "height");
+ }
+
+ // Fast scroll
+ child = FindNode(node, "fastscroll");
+ if (child)
+ {
+ mFastScrollLineColor = LoadAttrColor(child, "linecolor");
+ mFastScrollRectColor = LoadAttrColor(child, "rectcolor");
+
+ mFastScrollW = LoadAttrIntScaleX(child, "w");
+ mFastScrollLineW = LoadAttrIntScaleX(child, "linew");
+ mFastScrollRectW = LoadAttrIntScaleX(child, "rectw");
+ mFastScrollRectH = LoadAttrIntScaleY(child, "recth");
+ }
+
+ // Retrieve the line height
+ mFontHeight = mFont->GetHeight();
+ actualItemHeight = mFontHeight + mItemSpacing + mSeparatorH;
+
+ // Load the header if it exists
+ child = FindNode(node, "header");
+ if (child)
+ {
+ mHeaderH = mFontHeight;
+ mHeaderIcon = LoadAttrImage(child, "icon");
+ mHeaderBackgroundColor = LoadAttrColor(child, "background", mBackgroundColor);
+ mHeaderFontColor = LoadAttrColor(child, "textcolor", mFontColor);
+ mHeaderSeparatorColor = LoadAttrColor(child, "separatorcolor", mSeparatorColor);
+ mHeaderSeparatorH = LoadAttrIntScaleY(child, "separatorheight", mSeparatorH);
+
+ if (mHeaderIcon && mHeaderIcon->GetResource())
+ {
+ mHeaderIconWidth = mHeaderIcon->GetWidth();
+ mHeaderIconHeight = mHeaderIcon->GetHeight();
+ if (mHeaderIconHeight > mHeaderH)
+ mHeaderH = mHeaderIconHeight;
+ if (mHeaderIconWidth > maxIconWidth)
+ maxIconWidth = mHeaderIconWidth;
+ }
+
+ mHeaderH += mItemSpacing + mHeaderSeparatorH;
+ if (mHeaderH < actualItemHeight)
+ mHeaderH = actualItemHeight;
+ }
+
+ if (actualItemHeight / 3 > 6)
+ touchDebounce = actualItemHeight / 3;
+}
+
+GUIScrollList::~GUIScrollList()
+{
+}
+
+void GUIScrollList::SetMaxIconSize(int w, int h)
+{
+ if (w > maxIconWidth)
+ maxIconWidth = w;
+ if (h > maxIconHeight)
+ maxIconHeight = h;
+ if (maxIconHeight > mFontHeight) {
+ actualItemHeight = maxIconHeight + mItemSpacing + mSeparatorH;
+ if (mHeaderH > 0 && actualItemHeight > mHeaderH)
+ mHeaderH = actualItemHeight;
+ }
+}
+
+void GUIScrollList::SetVisibleListLocation(size_t list_index)
+{
+ // This will make sure that the item indicated by list_index is visible on the screen
+ size_t lines = GetDisplayItemCount();
+
+ if (list_index <= (unsigned)firstDisplayedItem) {
+ // list_index is above the currently displayed items, put the selected item at the very top
+ firstDisplayedItem = list_index;
+ y_offset = 0;
+ } else if (list_index >= firstDisplayedItem + lines) {
+ // list_index is below the currently displayed items, put the selected item at the very bottom
+ firstDisplayedItem = list_index - lines + 1;
+ if (GetDisplayRemainder() != 0) {
+ // There's a partial row displayed, set the scrolling offset so that the selected item really is at the very bottom
+ firstDisplayedItem--;
+ y_offset = GetDisplayRemainder() - actualItemHeight;
+ } else {
+ // There's no partial row so zero out the offset
+ y_offset = 0;
+ }
+ if (firstDisplayedItem < 0)
+ firstDisplayedItem = 0;
+ }
+ scrollingSpeed = 0; // stop kinetic scrolling on setting visible location
+ mUpdate = 1;
+}
+
+int GUIScrollList::Render(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ // First step, fill background
+ gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, mBackgroundColor.alpha);
+ gr_fill(mRenderX, mRenderY + mHeaderH, mRenderW, mRenderH - mHeaderH);
+
+ // don't paint outside of the box
+ gr_clip(mRenderX, mRenderY, mRenderW, mRenderH);
+
+ // Next, render the background resource (if it exists)
+ if (mBackground && mBackground->GetResource())
+ {
+ int BackgroundW = mBackground->GetWidth();
+ int BackgroundH = mBackground->GetHeight();
+ int BackgroundX = mRenderX + ((mRenderW - BackgroundW) / 2);
+ int BackgroundY = mRenderY + ((mRenderH - BackgroundH) / 2);
+ gr_blit(mBackground->GetResource(), 0, 0, BackgroundW, BackgroundH, BackgroundX, BackgroundY);
+ }
+
+ // This tells us how many full lines we can actually render
+ size_t lines = GetDisplayItemCount();
+
+ size_t listSize = GetItemCount();
+ int listW = mRenderW; // this is only used for the separators - the list items are rendered in the full width of the list
+
+ if (listSize <= lines) {
+ hasScroll = false;
+ scrollingSpeed = 0;
+ lines = listSize;
+ y_offset = 0;
+ } else {
+ hasScroll = true;
+ listW -= mFastScrollW; // space for fast scroll
+ lines++;
+ if (lines < listSize)
+ lines++;
+ }
+
+ int yPos = mRenderY + mHeaderH + y_offset;
+
+ // render all visible items
+ for (size_t line = 0; line < lines; line++)
+ {
+ size_t itemindex = line + firstDisplayedItem;
+ if (itemindex >= listSize)
+ break;
+
+ RenderItem(itemindex, yPos, itemindex == selectedItem);
+
+ // Add the separator
+ gr_color(mSeparatorColor.red, mSeparatorColor.green, mSeparatorColor.blue, mSeparatorColor.alpha);
+ gr_fill(mRenderX, yPos + actualItemHeight - mSeparatorH, listW, mSeparatorH);
+
+ // Move the yPos
+ yPos += actualItemHeight;
+ }
+
+ // Render the Header (last so that it overwrites the top most row for per pixel scrolling)
+ yPos = mRenderY;
+ if (mHeaderH > 0) {
+ // First step, fill background
+ gr_color(mHeaderBackgroundColor.red, mHeaderBackgroundColor.green, mHeaderBackgroundColor.blue, mHeaderBackgroundColor.alpha);
+ gr_fill(mRenderX, mRenderY, mRenderW, mHeaderH);
+
+ int IconOffsetX = 0;
+
+ // render the icon if it exists
+ if (mHeaderIcon && mHeaderIcon->GetResource())
+ {
+ gr_blit(mHeaderIcon->GetResource(), 0, 0, mHeaderIconWidth, mHeaderIconHeight, mRenderX + ((mHeaderIconWidth - maxIconWidth) / 2), (yPos + (int)((mHeaderH - mHeaderIconHeight) / 2)));
+ IconOffsetX = maxIconWidth;
+ }
+
+ // render the text
+ gr_color(mHeaderFontColor.red, mHeaderFontColor.green, mHeaderFontColor.blue, mHeaderFontColor.alpha);
+ gr_textEx(mRenderX + IconOffsetX + 5, yPos + (int)((mHeaderH - mFontHeight) / 2), mLastHeaderValue.c_str(), mFont->GetResource());
+
+ // Add the separator
+ gr_color(mHeaderSeparatorColor.red, mHeaderSeparatorColor.green, mHeaderSeparatorColor.blue, mHeaderSeparatorColor.alpha);
+ gr_fill(mRenderX, yPos + mHeaderH - mHeaderSeparatorH, mRenderW, mHeaderSeparatorH);
+ }
+
+ // reset clipping
+ gr_noclip();
+
+ // render fast scroll
+ if (hasScroll) {
+ int fWidth = mRenderW - listW;
+ int fHeight = mRenderH - mHeaderH;
+ int centerX = listW + mRenderX + fWidth / 2;
+
+ // first determine the total list height and where we are in the list
+ int totalHeight = GetItemCount() * actualItemHeight; // total height of the full list in pixels
+ int topPos = firstDisplayedItem * actualItemHeight - y_offset;
+
+ // now scale it proportionally to the scrollbar height
+ int boxH = fHeight * fHeight / totalHeight; // proportional height of the displayed portion
+ boxH = std::max(boxH, mFastScrollRectH); // but keep a minimum height
+ int boxY = (fHeight - boxH) * topPos / (totalHeight - fHeight); // pixels relative to top of list
+ int boxW = mFastScrollRectW;
+
+ int x = centerX - boxW / 2;
+ int y = mRenderY + mHeaderH + boxY;
+
+ // line above and below box (needs to be split because box can be transparent)
+ gr_color(mFastScrollLineColor.red, mFastScrollLineColor.green, mFastScrollLineColor.blue, mFastScrollLineColor.alpha);
+ gr_fill(centerX - mFastScrollLineW / 2, mRenderY + mHeaderH, mFastScrollLineW, boxY);
+ gr_fill(centerX - mFastScrollLineW / 2, y + boxH, mFastScrollLineW, fHeight - boxY - boxH);
+
+ // box
+ gr_color(mFastScrollRectColor.red, mFastScrollRectColor.green, mFastScrollRectColor.blue, mFastScrollRectColor.alpha);
+ gr_fill(x, y, boxW, boxH);
+
+ mFastScrollRectCurrentY = boxY;
+ mFastScrollRectCurrentH = boxH;
+ }
+ mUpdate = 0;
+ return 0;
+}
+
+void GUIScrollList::RenderItem(size_t itemindex, int yPos, bool selected)
+{
+ RenderStdItem(yPos, selected, NULL, "implement RenderItem!");
+}
+
+void GUIScrollList::RenderStdItem(int yPos, bool selected, ImageResource* icon, const char* text, int iconAndTextH)
+{
+ if (hasHighlightColor && selected) {
+ // Highlight the item background of the selected item
+ gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
+ gr_fill(mRenderX, yPos, mRenderW, actualItemHeight);
+ }
+
+ if (selected) {
+ // Use the highlight color for the font
+ gr_color(mFontHighlightColor.red, mFontHighlightColor.green, mFontHighlightColor.blue, mFontHighlightColor.alpha);
+ } else {
+ // Set the color for the font
+ gr_color(mFontColor.red, mFontColor.green, mFontColor.blue, mFontColor.alpha);
+ }
+
+ if (!iconAndTextH)
+ iconAndTextH = actualItemHeight;
+
+ // render icon
+ if (icon && icon->GetResource()) {
+ int iconH = icon->GetHeight();
+ int iconW = icon->GetWidth();
+ int iconY = yPos + (iconAndTextH - iconH) / 2;
+ int iconX = mRenderX + (maxIconWidth - iconW) / 2;
+ gr_blit(icon->GetResource(), 0, 0, iconW, iconH, iconX, iconY);
+ }
+
+ // render label text
+ int textX = mRenderX + maxIconWidth + 5;
+ int textY = yPos + (iconAndTextH - mFontHeight) / 2;
+ gr_textEx(textX, textY, text, mFont->GetResource());
+}
+
+int GUIScrollList::Update(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ if (!mHeaderIsStatic) {
+ std::string newValue = gui_parse_text(mHeaderText);
+ if (mLastHeaderValue != newValue) {
+ mLastHeaderValue = newValue;
+ mUpdate = 1;
+ }
+ }
+
+ // Handle kinetic scrolling
+ // maximum number of items to scroll per update
+ float maxItemsScrolledPerFrame = std::max(2.5, float(GetDisplayItemCount() / 4) + 0.5);
+
+ int maxScrollDistance = actualItemHeight * maxItemsScrolledPerFrame;
+ int oldScrollingSpeed = scrollingSpeed;
+ if (scrollingSpeed == 0) {
+ // Do nothing
+ return 0;
+ } else if (scrollingSpeed > 0) {
+ if (scrollingSpeed < maxScrollDistance)
+ y_offset += scrollingSpeed;
+ else
+ y_offset += maxScrollDistance;
+ scrollingSpeed *= SCROLLING_SPEED_DECREMENT;
+ if (scrollingSpeed == oldScrollingSpeed)
+ --scrollingSpeed;
+ } else if (scrollingSpeed < 0) {
+ if (abs(scrollingSpeed) < maxScrollDistance)
+ y_offset += scrollingSpeed;
+ else
+ y_offset -= maxScrollDistance;
+ scrollingSpeed *= SCROLLING_SPEED_DECREMENT;
+ if (scrollingSpeed == oldScrollingSpeed)
+ ++scrollingSpeed;
+ }
+ if (abs(scrollingSpeed) < SCROLLING_FLOOR)
+ scrollingSpeed = 0;
+ HandleScrolling();
+ mUpdate = 1;
+
+ return 0;
+}
+
+size_t GUIScrollList::HitTestItem(int x, int y)
+{
+ // We only care about y position
+ if (y < mRenderY || y - mRenderY <= mHeaderH || y - mRenderY > mRenderH)
+ return NO_ITEM;
+
+ int startSelection = (y - mRenderY - mHeaderH);
+
+ // Locate the correct item
+ size_t actualSelection = firstDisplayedItem;
+ int selectY = y_offset;
+ while (selectY + actualItemHeight < startSelection) {
+ selectY += actualItemHeight;
+ actualSelection++;
+ }
+
+ if (actualSelection < GetItemCount())
+ return actualSelection;
+
+ return NO_ITEM;
+}
+
+int GUIScrollList::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if(!isConditionTrue())
+ return -1;
+
+ switch (state)
+ {
+ case TOUCH_START:
+ if (hasScroll && x >= mRenderX + mRenderW - mFastScrollW) {
+ fastScroll = 1; // Initial touch is in the fast scroll region
+ int fastScrollBoxTop = mFastScrollRectCurrentY + mRenderY + mHeaderH;
+ int fastScrollBoxBottom = fastScrollBoxTop + mFastScrollRectCurrentH;
+ if (y >= fastScrollBoxTop && y < fastScrollBoxBottom)
+ // user grabbed the fastscroll bar
+ // try to keep the initially touched part of the scrollbar under the finger
+ mFastScrollRectTouchY = y - fastScrollBoxTop;
+ else
+ // user tapped outside the fastscroll bar
+ // center fastscroll rect on the initial touch position
+ mFastScrollRectTouchY = mFastScrollRectCurrentH / 2;
+ }
+
+ if (scrollingSpeed != 0) {
+ selectedItem = NO_ITEM; // this allows the user to tap the list to stop the scrolling without selecting the item they tap
+ scrollingSpeed = 0; // stop scrolling on a new touch
+ } else if (!fastScroll && allowSelection) {
+ // find out which item the user touched
+ selectedItem = HitTestItem(x, y);
+ }
+ if (selectedItem != NO_ITEM)
+ mUpdate = 1;
+ lastY = last2Y = y;
+ break;
+
+ case TOUCH_DRAG:
+ if (fastScroll)
+ {
+ int relY = y - mRenderY - mHeaderH; // touch position relative to window
+ int windowH = mRenderH - mHeaderH;
+ int totalHeight = GetItemCount() * actualItemHeight; // total height of the full list in pixels
+
+ // calculate new top position of the fastscroll bar relative to window
+ int newY = relY - mFastScrollRectTouchY;
+ // keep it fully inside the list
+ newY = std::min(std::max(newY, 0), windowH - mFastScrollRectCurrentH);
+
+ // now compute the new scroll position for the list
+ int newTopPos = newY * (totalHeight - windowH) / (windowH - mFastScrollRectCurrentH); // new top pixel of list
+ newTopPos = std::min(newTopPos, totalHeight - windowH); // account for rounding errors
+ firstDisplayedItem = newTopPos / actualItemHeight;
+ y_offset = - newTopPos % actualItemHeight;
+
+ selectedItem = NO_ITEM;
+ mUpdate = 1;
+ scrollingSpeed = 0; // prevent kinetic scrolling when using fast scroll
+ break;
+ }
+
+ // Provide some debounce on initial touches
+ if (selectedItem != NO_ITEM && abs(y - lastY) < touchDebounce) {
+ mUpdate = 1;
+ break;
+ }
+
+ selectedItem = NO_ITEM; // nothing is selected because we dragged too far
+ // Handle scrolling
+ if (hasScroll) {
+ y_offset += y - lastY; // adjust the scrolling offset based on the difference between the starting touch and the current touch
+ last2Y = lastY; // keep track of previous y locations so that we can tell how fast to scroll for kinetic scrolling
+ lastY = y; // update last touch to the current touch so we can tell how far and what direction we scroll for the next touch event
+
+ HandleScrolling();
+ } else
+ y_offset = 0;
+ mUpdate = 1;
+ break;
+
+ case TOUCH_RELEASE:
+ if (fastScroll)
+ mUpdate = 1; // get rid of touch effects on the fastscroll bar
+ fastScroll = 0;
+ if (selectedItem != NO_ITEM) {
+ // We've selected an item!
+ NotifySelect(selectedItem);
+ mUpdate = 1;
+
+ DataManager::Vibrate("tw_button_vibrate");
+ selectedItem = NO_ITEM;
+ } else {
+ // Start kinetic scrolling
+ scrollingSpeed = lastY - last2Y;
+ if (abs(scrollingSpeed) < touchDebounce)
+ scrollingSpeed = 0;
+ }
+ case TOUCH_REPEAT:
+ case TOUCH_HOLD:
+ break;
+ }
+ return 0;
+}
+
+void GUIScrollList::HandleScrolling()
+{
+ // handle dragging downward, scrolling upward
+ // the offset should always be <= 0 and > -actualItemHeight, adjust the first display row and offset as needed
+ while(firstDisplayedItem && y_offset > 0) {
+ firstDisplayedItem--;
+ y_offset -= actualItemHeight;
+ }
+ if (firstDisplayedItem == 0 && y_offset > 0) {
+ y_offset = 0; // user kept dragging downward past the top of the list, so always reset the offset to 0 since we can't scroll any further in this direction
+ scrollingSpeed = 0; // stop kinetic scrolling
+ }
+
+ // handle dragging upward, scrolling downward
+ int totalSize = GetItemCount();
+ int lines = GetDisplayItemCount(); // number of full lines our list can display at once
+ int bottom_offset = GetDisplayRemainder() - actualItemHeight; // extra display area that can display a partial line for per pixel scrolling
+
+ // the offset should always be <= 0 and > -actualItemHeight, adjust the first display row and offset as needed
+ while (firstDisplayedItem + lines + (bottom_offset ? 1 : 0) < totalSize && abs(y_offset) > actualItemHeight) {
+ firstDisplayedItem++;
+ y_offset += actualItemHeight;
+ }
+ // Check if we dragged too far, set the list at the bottom and adjust offset as needed
+ if (bottom_offset != 0 && firstDisplayedItem + lines + 1 >= totalSize && y_offset <= bottom_offset) {
+ firstDisplayedItem = totalSize - lines - 1;
+ y_offset = bottom_offset;
+ scrollingSpeed = 0; // stop kinetic scrolling
+ } else if (firstDisplayedItem + lines >= totalSize && y_offset < 0) {
+ firstDisplayedItem = totalSize - lines;
+ y_offset = 0;
+ scrollingSpeed = 0; // stop kinetic scrolling
+ }
+}
+
+int GUIScrollList::GetDisplayItemCount()
+{
+ return (mRenderH - mHeaderH) / (actualItemHeight);
+}
+
+int GUIScrollList::GetDisplayRemainder()
+{
+ return (mRenderH - mHeaderH) % actualItemHeight;
+}
+
+int GUIScrollList::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIObject::NotifyVarChange(varName, value);
+
+ if(!isConditionTrue())
+ return 0;
+
+ if (!mHeaderIsStatic) {
+ std::string newValue = gui_parse_text(mHeaderText);
+ if (mLastHeaderValue != newValue) {
+ mLastHeaderValue = newValue;
+ firstDisplayedItem = 0;
+ y_offset = 0;
+ scrollingSpeed = 0; // stop kinetic scrolling on variable changes
+ mUpdate = 1;
+ }
+ }
+ return 0;
+}
+
+int GUIScrollList::SetRenderPos(int x, int y, int w /* = 0 */, int h /* = 0 */)
+{
+ mRenderX = x;
+ mRenderY = y;
+ if (w || h)
+ {
+ mRenderW = w;
+ mRenderH = h;
+ }
+ SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+ mUpdate = 1;
+ return 0;
+}
+
+void GUIScrollList::SetPageFocus(int inFocus)
+{
+ if (inFocus) {
+ NotifyVarChange("", ""); // This forces a check for the header text
+ scrollingSpeed = 0; // stop kinetic scrolling on page changes
+ mUpdate = 1;
+ }
+}
diff --git a/gui/slider.cpp b/gui/slider.cpp
new file mode 100644
index 000000000..a3884474b
--- /dev/null
+++ b/gui/slider.cpp
@@ -0,0 +1,201 @@
+// slider.cpp - GUISlider object
+// Pulled & ported from https://raw.github.com/agrabren/RecoverWin/master/gui/slider.cpp
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include "../data.hpp"
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUISlider::GUISlider(xml_node<>* node) : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ sAction = NULL;
+ sSliderLabel = NULL;
+ sSlider = NULL;
+ sSliderUsed = NULL;
+ sTouch = NULL;
+ sTouchW = 20;
+
+ if (!node)
+ {
+ LOGERR("GUISlider created without XML node\n");
+ return;
+ }
+
+ // Load the resources
+ child = FindNode(node, "resource");
+ if (child)
+ {
+ sSlider = LoadAttrImage(child, "base");
+ sSliderUsed = LoadAttrImage(child, "used");
+ sTouch = LoadAttrImage(child, "touch");
+ }
+
+ // Load the text label
+ sSliderLabel = new GUIText(node);
+ if (sSliderLabel->Render() < 0)
+ {
+ delete sSliderLabel;
+ sSliderLabel = NULL;
+ }
+
+ // Load the placement
+ Placement TextPlacement = CENTER;
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH, &TextPlacement);
+
+ mRenderW = sSlider->GetWidth();
+ mRenderH = sSlider->GetHeight();
+ if (TextPlacement == CENTER || TextPlacement == CENTER_X_ONLY) {
+ mRenderX = mRenderX - (mRenderW / 2);
+ if (TextPlacement == CENTER) {
+ mRenderY = mRenderY - (mRenderH / 2);
+ }
+ }
+ if (sSliderLabel) {
+ int sTextX = mRenderX + (mRenderW / 2);
+ int w, h;
+ sSliderLabel->GetCurrentBounds(w, h);
+ int sTextY = mRenderY + ((mRenderH - h) / 2);
+ sSliderLabel->SetRenderPos(sTextX, sTextY);
+ }
+ if (sTouch && sTouch->GetResource())
+ {
+ sTouchW = sTouch->GetWidth(); // Width of the "touch image" that follows the touch (arrow)
+ sTouchH = sTouch->GetHeight(); // Height of the "touch image" that follows the touch (arrow)
+ }
+
+ //LOGINFO("mRenderW: %i mTouchW: %i\n", mRenderW, mTouchW);
+ mActionX = mRenderX;
+ mActionY = mRenderY;
+ mActionW = mRenderW;
+ mActionH = mRenderH;
+
+ sAction = new GUIAction(node);
+
+ sCurTouchX = mRenderX;
+ sUpdate = 1;
+}
+
+GUISlider::~GUISlider()
+{
+ delete sAction;
+ delete sSliderLabel;
+}
+
+int GUISlider::Render(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ if (!sSlider || !sSlider->GetResource())
+ return -1;
+
+ // Draw the slider
+ gr_blit(sSlider->GetResource(), 0, 0, mRenderW, mRenderH, mRenderX, mRenderY);
+
+ // Draw the used
+ if (sSliderUsed && sSliderUsed->GetResource() && sCurTouchX > mRenderX)
+ gr_blit(sSliderUsed->GetResource(), 0, 0, sCurTouchX - mRenderX, mRenderH, mRenderX, mRenderY);
+
+ // Draw the touch icon
+ if (sTouch && sTouch->GetResource())
+ gr_blit(sTouch->GetResource(), 0, 0, sTouchW, sTouchH, sCurTouchX, (mRenderY + ((mRenderH - sTouchH) / 2)));
+
+ if (sSliderLabel) {
+ int ret = sSliderLabel->Render();
+ if (ret < 0) return ret;
+ }
+
+ sUpdate = 0;
+ return 0;
+}
+
+int GUISlider::Update(void)
+{
+ if(!isConditionTrue())
+ return 0;
+
+ if (sUpdate)
+ return 2;
+ return 0;
+}
+
+int GUISlider::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if(!isConditionTrue())
+ return -1;
+
+ static bool dragging = false;
+
+ switch (state)
+ {
+ case TOUCH_START:
+ if (x >= mRenderX && x <= mRenderX + sTouchW &&
+ y >= mRenderY && y <= mRenderY + mRenderH)
+ {
+ sCurTouchX = x - (sTouchW / 2);
+ if (sCurTouchX < mRenderX)
+ sCurTouchX = mRenderX;
+ dragging = true;
+ }
+ break;
+
+ case TOUCH_DRAG:
+ if (!dragging)
+ return 0;
+ if (y < mRenderY - sTouchH || y > mRenderY + (sTouchH * 2))
+ {
+ sCurTouchX = mRenderX;
+ dragging = false;
+ sUpdate = 1;
+ break;
+ }
+ sCurTouchX = x - (sTouchW / 2);
+ if (sCurTouchX < mRenderX)
+ sCurTouchX = mRenderX;
+ if (sCurTouchX > mRenderX + mRenderW - sTouchW)
+ sCurTouchX = mRenderX + mRenderW - sTouchW;
+ sUpdate = 1;
+ break;
+
+ case TOUCH_RELEASE:
+ if (!dragging)
+ return 0;
+
+ if (sCurTouchX >= mRenderX + mRenderW - sTouchW) {
+ DataManager::Vibrate("tw_button_vibrate");
+ sAction->doActions();
+ }
+
+ sCurTouchX = mRenderX;
+ dragging = false;
+ sUpdate = 1;
+ case TOUCH_REPEAT:
+ case TOUCH_HOLD:
+ break;
+ }
+ return 0;
+}
diff --git a/gui/slidervalue.cpp b/gui/slidervalue.cpp
new file mode 100644
index 000000000..3974c37d0
--- /dev/null
+++ b/gui/slidervalue.cpp
@@ -0,0 +1,422 @@
+// slidervalue.cpp - GUISliderValue object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUISliderValue::GUISliderValue(xml_node<>* node) : GUIObject(node)
+{
+ xml_attribute<>* attr;
+ xml_node<>* child;
+
+ mMin = 0;
+ mMax = 100;
+ mValue = 0;
+ mLineH = 2;
+ mLinePadding = 10;
+ mSliderW = 5;
+ mSliderH = 30;
+ mLineX = 0;
+ mLineY = 0;
+ mValueStr = NULL;
+ mAction = NULL;
+ mShowCurr = true;
+ mShowRange = false;
+ mChangeOnDrag = false;
+ mRendered = false;
+ mBackgroundImage = NULL;
+ mHandleImage = NULL;
+ mHandleHoverImage = NULL;
+ mDragging = false;
+
+ mLabel = NULL;
+ ConvertStrToColor("white", &mTextColor);
+ ConvertStrToColor("white", &mLineColor);
+ ConvertStrToColor("blue", &mSliderColor);
+
+ if (!node)
+ {
+ LOGERR("GUISliderValue created without XML node\n");
+ return;
+ }
+
+ mLabel = new GUIText(node);
+ if(mLabel->Render() < 0)
+ {
+ delete mLabel;
+ mLabel = NULL;
+ }
+
+ mAction = new GUIAction(node);
+
+ child = FindNode(node, "font");
+ if (child)
+ {
+ mFont = LoadAttrFont(child, "resource");
+ mTextColor = LoadAttrColor(child, "color", mTextColor);
+ }
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW);
+
+ child = FindNode(node, "colors");
+ if (child)
+ {
+ mLineColor = LoadAttrColor(child, "line");
+ mSliderColor = LoadAttrColor(child, "slider");
+ }
+
+ child = FindNode(node, "resource");
+ if (child)
+ {
+ mBackgroundImage = LoadAttrImage(child, "background");
+ mHandleImage = LoadAttrImage(child, "handle");
+ mHandleHoverImage = LoadAttrImage(child, "handlehover");
+ }
+
+ child = FindNode(node, "data");
+ if (child)
+ {
+ attr = child->first_attribute("variable");
+ if (attr)
+ mVariable = attr->value();
+
+ attr = child->first_attribute("min");
+ if (attr)
+ {
+ mMinStr = gui_parse_text(attr->value());
+ mMin = atoi(mMinStr.c_str());
+ }
+
+ attr = child->first_attribute("max");
+ if (attr)
+ {
+ mMaxStr = gui_parse_text(attr->value());
+ mMax = atoi(mMaxStr.c_str());
+ }
+
+ if (mMin > mMax)
+ mMin = mMax;
+
+ attr = child->first_attribute("default");
+ if (attr)
+ {
+ string parsevalue = gui_parse_text(attr->value());
+ int def = atoi(parsevalue.c_str());
+
+ if (def < mMin)
+ def = mMin;
+ else if (def > mMax)
+ def = mMax;
+ DataManager::SetValue(mVariable, def);
+ }
+
+ attr = child->first_attribute("showrange");
+ if (attr)
+ mShowRange = atoi(attr->value());
+
+ attr = child->first_attribute("showcurr");
+ if (attr)
+ mShowCurr = atoi(attr->value());
+
+ attr = child->first_attribute("changeondrag");
+ if (attr)
+ mChangeOnDrag = atoi(attr->value());
+ }
+
+ child = FindNode(node, "dimensions");
+ if (child)
+ {
+ mLineH = LoadAttrIntScaleY(child, "lineh", mLineH);
+ mLinePadding = LoadAttrIntScaleX(child, "linepadding", mLinePadding);
+ mSliderW = LoadAttrIntScaleX(child, "sliderw", mSliderW);
+ mSliderH = LoadAttrIntScaleY(child, "sliderh", mSliderH);
+ }
+
+ mFontHeight = mFont->GetHeight();
+
+ if(mShowCurr)
+ {
+ int maxLen = std::max(strlen(mMinStr.c_str()), strlen(mMaxStr.c_str()));
+ mValueStr = new char[maxLen+1];
+ }
+
+ loadValue(true);
+
+ if (mShowRange)
+ {
+ int textW = std::max(measureText(mMaxStr), measureText(mMinStr));
+ mLinePadding += textW;
+ }
+
+ SetRenderPos(mRenderX, mRenderY, mRenderW);
+}
+
+GUISliderValue::~GUISliderValue()
+{
+ delete mLabel;
+ delete mAction;
+ delete[] mValueStr;
+}
+
+void GUISliderValue::loadValue(bool force)
+{
+ if(!mVariable.empty())
+ {
+ int value = DataManager::GetIntValue(mVariable);
+ if(mValue == value && !force)
+ return;
+
+ mValue = value;
+ }
+
+ mValue = std::max(mValue, mMin);
+ mValue = std::min(mValue, mMax);
+ mValuePct = pctFromValue(mValue);
+ mRendered = false;
+}
+
+int GUISliderValue::SetRenderPos(int x, int y, int w, int h)
+{
+ mRenderX = x;
+ mRenderY = y;
+ if (w || h)
+ {
+ mRenderW = w;
+ mRenderH = h;
+ }
+
+ mRenderH = mSliderH;
+ if(mShowCurr)
+ mRenderH += mFontHeight;
+
+ if (mLabel)
+ {
+ int lw, lh;
+ mLabel->GetCurrentBounds(lw, lh);
+ int textX = mRenderX + (mRenderW/2 - lw/2);
+
+ mLabel->SetRenderPos(textX, mRenderY);
+
+ y += lh;
+ mRenderH += lh;
+ }
+
+ mSliderY = y;
+
+ mActionX = mRenderX;
+ mActionY = mRenderY;
+ mActionW = mRenderW;
+ mActionH = mRenderH;
+
+ if(mBackgroundImage && mBackgroundImage->GetResource())
+ {
+ mLineW = mBackgroundImage->GetWidth();
+ mLineH = mBackgroundImage->GetHeight();
+ }
+ else
+ mLineW = mRenderW - (mLinePadding * 2);
+
+ mLineY = y + (mSliderH/2 - mLineH/2);
+ mLineX = mRenderX + (mRenderW/2 - mLineW/2);
+
+ return 0;
+}
+
+int GUISliderValue::measureText(const std::string& str)
+{
+ void* fontResource = NULL;
+ if (mFont) fontResource = mFont->GetResource();
+
+ return gr_measureEx(str.c_str(), fontResource);
+}
+
+int GUISliderValue::Render(void)
+{
+ if (!isConditionTrue())
+ {
+ mRendered = false;
+ return 0;
+ }
+
+ if(mLabel)
+ {
+ int w, h;
+ mLabel->GetCurrentBounds(w, h);
+ if (w != mLabelW) {
+ mLabelW = w;
+ int textX = mRenderX + (mRenderW/2 - mLabelW/2);
+ mLabel->SetRenderPos(textX, mRenderY);
+ }
+ int res = mLabel->Render();
+ if(res < 0)
+ return res;
+ }
+
+ // line
+ if(mBackgroundImage && mBackgroundImage->GetResource())
+ {
+ gr_blit(mBackgroundImage->GetResource(), 0, 0, mLineW, mLineH, mLineX, mLineY);
+ }
+ else
+ {
+ gr_color(mLineColor.red, mLineColor.green, mLineColor.blue, mLineColor.alpha);
+ gr_fill(mLineX, mLineY, mLineW, mLineH);
+ }
+
+ // slider
+ uint32_t sliderX = mLineX + (mValuePct*(mLineW - mSliderW))/100;
+
+ if(mHandleImage && mHandleImage->GetResource())
+ {
+ gr_surface s = mHandleImage->GetResource();
+ if(mDragging && mHandleHoverImage && mHandleHoverImage->GetResource())
+ s = mHandleHoverImage->GetResource();
+ gr_blit(s, 0, 0, mSliderW, mSliderH, sliderX, mLineY + (mLineH/2 - mSliderH/2));
+ }
+ else
+ {
+ gr_color(mSliderColor.red, mSliderColor.green, mSliderColor.blue, mSliderColor.alpha);
+ gr_fill(sliderX, mSliderY, mSliderW, mSliderH);
+ }
+
+ void *fontResource = NULL;
+ if(mFont) fontResource = mFont->GetResource();
+ gr_color(mTextColor.red, mTextColor.green, mTextColor.blue, mTextColor.alpha);
+ if(mShowRange)
+ {
+ int rangeY = (mLineY - mLineH/2) - mFontHeight/2;
+ gr_textEx(mRenderX + mPadding/2, rangeY, mMinStr.c_str(), fontResource);
+ gr_textEx(mLineX + mLineW + mPadding/2, rangeY, mMaxStr.c_str(), fontResource);
+ }
+
+ if(mValueStr && mShowCurr)
+ {
+ sprintf(mValueStr, "%d", mValue);
+ int textW = measureText(mValueStr);
+ gr_textEx(mRenderX + (mRenderW/2 - textW/2), mSliderY+mSliderH, mValueStr, fontResource);
+ }
+
+ mRendered = true;
+ return 0;
+}
+
+int GUISliderValue::Update(void)
+{
+ if (!isConditionTrue())
+ return mRendered ? 2 : 0;
+ if (!mRendered)
+ return 2;
+
+ if(mLabel)
+ return mLabel->Update();
+ return 0;
+}
+
+int GUISliderValue::valueFromPct(float pct)
+{
+ int range = abs(mMax - mMin);
+ return mMin + (pct * range) / 100;
+}
+
+float GUISliderValue::pctFromValue(int value)
+{
+ return float((value - mMin) * 100) / abs(mMax - mMin);
+}
+
+int GUISliderValue::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+ if (!isConditionTrue())
+ return -1;
+
+ switch (state)
+ {
+ case TOUCH_START:
+ if (x >= mLineX && x <= mLineX + mLineW &&
+ y >= mRenderY && y <= mRenderY + mRenderH)
+ {
+ mDragging = true;
+ }
+ // no break
+ case TOUCH_DRAG:
+ {
+ if (!mDragging) return 0;
+
+ x = std::max(mLineX + mSliderW/2, x);
+ x = std::min(mLineX + mLineW - mSliderW/2, x);
+
+ mValuePct = float(((x - (mLineX + mSliderW/2)) * 100) / (mLineW - mSliderW));
+ int newVal = valueFromPct(mValuePct);
+ if (newVal != mValue) {
+ mRendered = false;
+ mValue = newVal;
+ if (mChangeOnDrag) {
+ if (!mVariable.empty())
+ DataManager::SetValue(mVariable, mValue);
+ if (mAction)
+ mAction->doActions();
+ }
+ }
+ break;
+ }
+ case TOUCH_RELEASE:
+ {
+ if (!mDragging) return 0;
+ mDragging = false;
+
+ if (!mVariable.empty())
+ DataManager::SetValue(mVariable, mValue);
+ if (mAction)
+ mAction->doActions();
+ break;
+ }
+ case TOUCH_REPEAT:
+ case TOUCH_HOLD:
+ break;
+ }
+ return 0;
+}
+
+int GUISliderValue::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIObject::NotifyVarChange(varName, value);
+
+ if (mLabel)
+ mLabel->NotifyVarChange(varName, value);
+ if (varName == mVariable) {
+ int newVal = atoi(value.c_str());
+ if(newVal != mValue) {
+ mValue = newVal;
+ mValuePct = pctFromValue(mValue);
+ mRendered = false;
+ }
+ }
+ return 0;
+}
+
+void GUISliderValue::SetPageFocus(int inFocus)
+{
+ if (inFocus)
+ loadValue();
+}
diff --git a/gui/text.cpp b/gui/text.cpp
new file mode 100644
index 000000000..effb9359b
--- /dev/null
+++ b/gui/text.cpp
@@ -0,0 +1,170 @@
+// text.cpp - GUIText object
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../twcommon.h"
+#include "../minuitwrp/minui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+
+GUIText::GUIText(xml_node<>* node)
+ : GUIObject(node)
+{
+ mFont = NULL;
+ mIsStatic = 1;
+ mVarChanged = 0;
+ mFontHeight = 0;
+ maxWidth = 0;
+ charSkip = 0;
+ isHighlighted = false;
+
+ if (!node)
+ return;
+
+ // Load colors
+ mColor = LoadAttrColor(node, "color", COLOR(0,0,0,255));
+ mHighlightColor = LoadAttrColor(node, "highlightcolor", mColor);
+
+ // Load the font, and possibly override the color
+ mFont = LoadAttrFont(FindNode(node, "font"), "resource");
+ mColor = LoadAttrColor(FindNode(node, "font"), "color", mColor);
+ mHighlightColor = LoadAttrColor(FindNode(node, "font"), "highlightcolor", mColor);
+
+ // Load the placement
+ LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH, &mPlacement);
+
+ xml_node<>* child = FindNode(node, "text");
+ if (child) mText = child->value();
+
+ // Simple way to check for static state
+ mLastValue = gui_parse_text(mText);
+ if (mLastValue != mText) mIsStatic = 0;
+
+ mFontHeight = mFont->GetHeight();
+}
+
+int GUIText::Render(void)
+{
+ if (!isConditionTrue())
+ return 0;
+
+ void* fontResource = NULL;
+ if (mFont)
+ fontResource = mFont->GetResource();
+
+ mLastValue = gui_parse_text(mText);
+ string displayValue = mLastValue;
+
+ if (charSkip)
+ displayValue.erase(0, charSkip);
+
+ mVarChanged = 0;
+
+ int x = mRenderX, y = mRenderY;
+ int width = gr_measureEx(displayValue.c_str(), fontResource);
+
+ if (mPlacement != TOP_LEFT && mPlacement != BOTTOM_LEFT)
+ {
+ if (mPlacement == CENTER || mPlacement == CENTER_X_ONLY)
+ x -= (width / 2);
+ else
+ x -= width;
+ }
+ if (mPlacement != TOP_LEFT && mPlacement != TOP_RIGHT)
+ {
+ if (mPlacement == CENTER)
+ y -= (mFontHeight / 2);
+ else if (mPlacement == BOTTOM_LEFT || mPlacement == BOTTOM_RIGHT)
+ y -= mFontHeight;
+ }
+
+ if (isHighlighted)
+ gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
+ else
+ gr_color(mColor.red, mColor.green, mColor.blue, mColor.alpha);
+
+ if (maxWidth)
+ gr_textExW(x, y, displayValue.c_str(), fontResource, maxWidth + x);
+ else
+ gr_textEx(x, y, displayValue.c_str(), fontResource);
+ return 0;
+}
+
+int GUIText::Update(void)
+{
+ if (!isConditionTrue())
+ return 0;
+
+ static int updateCounter = 3;
+
+ // This hack just makes sure we update at least once a minute for things like clock and battery
+ if (updateCounter) updateCounter--;
+ else
+ {
+ mVarChanged = 1;
+ updateCounter = 3;
+ }
+
+ if (mIsStatic || !mVarChanged)
+ return 0;
+
+ std::string newValue = gui_parse_text(mText);
+ if (mLastValue == newValue)
+ return 0;
+ else
+ mLastValue = newValue;
+ return 2;
+}
+
+int GUIText::GetCurrentBounds(int& w, int& h)
+{
+ void* fontResource = NULL;
+
+ if (mFont)
+ fontResource = mFont->GetResource();
+
+ h = mFontHeight;
+ mLastValue = gui_parse_text(mText);
+ w = gr_measureEx(mLastValue.c_str(), fontResource);
+ return 0;
+}
+
+int GUIText::NotifyVarChange(const std::string& varName, const std::string& value)
+{
+ GUIObject::NotifyVarChange(varName, value);
+
+ mVarChanged = 1;
+ return 0;
+}
+
+int GUIText::SetMaxWidth(unsigned width)
+{
+ maxWidth = width;
+ mVarChanged = 1;
+ return 0;
+}
+
+int GUIText::SkipCharCount(unsigned skip)
+{
+ charSkip = skip;
+ mVarChanged = 1;
+ return 0;
+}
diff --git a/gui/twrp b/gui/twrp
new file mode 100644
index 000000000..e69de29bb
--- /dev/null
+++ b/gui/twrp