Parse configuration file 73/148373/12
authorPaweł Szewczyk <p.szewczyk@samsung.com>
Fri, 8 Sep 2017 12:32:06 +0000 (14:32 +0200)
committerPaweł Szewczyk <p.szewczyk@samsung.com>
Fri, 22 Sep 2017 09:11:28 +0000 (11:11 +0200)
Get GUI gonfiguration from file and parse it using libconfig.

Change-Id: I682a81eee1bc1db038bf53b19981a533f48c6d44
Signed-off-by: Paweł Szewczyk <p.szewczyk@samsung.com>
Signed-off-by: Łukasz Stelmach <l.stelmach@samsung.com>
Makefile.am
configure.ac
packaging/initrd-recovery.spec
src/librui/rui-menu.c
src/librui/rui-menu.h
src/librui/rui.c
src/system-recovery/50-system-recovery.list.m4.in
src/system-recovery/recovery-main.c
src/system-recovery/recovery-rui.c
src/system-recovery/system-recovery.cfg.m4.in [new file with mode: 0644]
src/system-recovery/system-recovery.h

index 9df4e35a3935fa947b3f40fb8cfb457173d8f6a1..8d90abcd0bd9ea712aaff8399ecfeb00da9625c4 100644 (file)
@@ -117,6 +117,7 @@ librui_la_LIBADD = \
 endif
 
 # ------------------------------------------------------------------------------
+system_recovery_datadir = $(SYSTEM_RECOVERY_DATA_DIR)
 system_recovery_imagedir = $(SYSTEM_RECOVERY_IMAGE_DIR)
 system_recovery_libexecdir = $(SYSTEM_RECOVERY_LIBEXEC_DIR)
 
@@ -128,11 +129,16 @@ system_recovery_SOURCES = \
 
 system_recovery_CFLAGS = \
        $(AM_CFLAGS) \
+       -DSYSTEM_RECOVERY_CONFIG_FILE=\""${system_recovery_datadir}/system-recovery.cfg"\" \
        -I $(librui_la_CFLAGS) \
        -I src/system-recovery
+       $(LIBCONFIG_CFLAGS) \
+       -I $(top_srcdir)/src/librui \
+       -I $(top_srcdir)/src/system-recovery
 
 system_recovery_LDADD = \
        $(AM_LIBS) \
+       $(LIBCONFIG_LIBS) \
        librui.la
 
 system_recovery_libexec_PROGRAMS = \
@@ -148,6 +154,9 @@ initrd_recovery_install_dropin_DATA += \
        src/system-recovery/50-system-recovery-sprd.list
 endif
 
+system_recovery_data_DATA = \
+       src/system-recovery/system-recovery.cfg
+
 system_recovery_libexec_SCRIPTS = \
        src/system-recovery/recovery-init
 
@@ -155,12 +164,14 @@ initrd_recovery_install_dropin_DATA += \
        src/system-recovery/50-system-recovery.list
 
 EXTRA_DIST += \
+       src/system-recovery/50-system-recovery.list.m4 \
        src/system-recovery/recovery-init.in \
-       src/system-recovery/50-system-recovery.list.m4
+       src/system-recovery/system-recovery.cfg.m4.in
 
 CLEANFILES += \
+       src/system-recovery/50-system-recovery.list \
        src/system-recovery/recovery-init \
-       src/system-recovery/50-system-recovery.list
+       src/system-recovery/system-recovery.cfg.m4
 
 # ------------------------------------------------------------------------------
 substitutions = \
@@ -174,6 +185,7 @@ substitutions = \
        '|INITRD_RECOVERY_LIBEXEC_DIR=$(INITRD_RECOVERY_LIBEXEC_DIR)|' \
        '|SYSTEM_RECOVERY_IMAGE_DIR=$(SYSTEM_RECOVERY_IMAGE_DIR)|' \
        '|SYSTEM_RECOVERY_LIBEXEC_DIR=$(SYSTEM_RECOVERY_LIBEXEC_DIR)|' \
+       '|SYSTEM_RECOVERY_DATA_DIR=$(SYSTEM_RECOVERY_DATA_DIR)|' \
        '|RECOVERY_GUI=$(RECOVERY_GUI)|'
 
 SED_PROCESS = \
index 4f131a7a7fe26da4a0002fac336368f913f6d7e0..98e9a49a131c83e09a6fde9ba5b2832b91491e8a 100644 (file)
@@ -64,6 +64,14 @@ M4_DEFINES=
 # ------------------------------------------------------------------------------
 AC_ARG_WITH([tdm],
        AS_HELP_STRING([--without-tdm], [disable TDM/TBM graphical backend (default: test)]))
+PKG_CHECK_MODULES([LIBCONFIG],
+       [libconfig >= 1.6],
+       have_libconfig=yes,
+       have_libconfig=no)
+
+if test "x$have_libconfig" = "xno"; then
+       AC_MSG_ERROR([libconfig not found])
+fi
 
 AC_ARG_ENABLE([recovery-gui],
         AS_HELP_STRING([--disable-recovery-gui], [disable recovery gui mode]),
index 4f83f80f5179c4c5685f721fe76df63c0027b97a..14da98f5718263dcf7d4430fb37684799602d6d6 100644 (file)
@@ -12,6 +12,7 @@ Source1001:     initrd-recovery.manifest
 BuildRequires:  autoconf
 BuildRequires:  automake
 BuildRequires:  libtool
+BuildRequires:  pkgconfig(libconfig)
 BuildRequires:  pkgconfig(libtdm)
 
 Requires:       system-recovery
@@ -154,6 +155,7 @@ mv %{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery.list \
 %files -n system-recovery
 %defattr(-,root,root,-)
 %manifest initrd-recovery.manifest
+%{_datadir}/system-recovery/system-recovery.cfg
 
 %files -n system-recovery-non_gui
 %{_datadir}/initrd-recovery/initrd.list.d/50-system-recovery.list.non_gui
index 65bb7f041439bc1e0d022aac7287cbbe2519ba54..e62128e7bcf3e35a805d2f2b4a6c04dcd1b88d90 100644 (file)
@@ -77,14 +77,18 @@ int rui_menu_cursor_down(rui_menu *menu)
 int rui_menu_action_run(rui_menu *menu)
 {
        int item_selected;
+       int ret;
 
        if (!menu || !menu->actions)
                return 0; /* Don't need to repaint */
 
        item_selected = menu->item_selected;
        rui_screen_switch(menu->actions[item_selected].screen_switch_to);
-       if (menu->actions[item_selected].action_handler)
-               menu->actions[item_selected].action_handler();
+       if (menu->actions[item_selected].action_handler) {
+               ret = system(menu->actions[item_selected].action_handler);
+               if (ret < 0)
+                       return ret;
+       }
 
        return 1; /* Repaint unconditionally. Just in case. */
 }
index c68efc123e9957ee15f0f15bed75c4e86b64ced8..881c03b5506ad0ba18adf7a1ab6d92eaf68eb615 100644 (file)
@@ -39,11 +39,10 @@ typedef enum {
 } rui_menu_item_id;
 
 struct rui_menu_t;
-typedef void (*rui_menu_action_handler)(void);
 
 typedef struct {
-       int                     screen_switch_to;
-       rui_menu_action_handler action_handler;
+        int                     screen_switch_to;
+        const char             *action_handler;
 } rui_menu_action;
 
 typedef struct rui_menu_t {
index 1626a3d21b7973138c1ae545fc0580b44048edfc..095485316869ab1e94c87827af5f859c51e10555 100644 (file)
@@ -47,7 +47,8 @@ void rui_draw(void)
        rui_screen *cs;
 
        cs = get_current_screen();
-       gr_set_color(cs->style->c_background);
+       if (cs->style)
+               gr_set_color(cs->style->c_background);
        gr_clear();
        rui_images_draw();
        rui_animations_draw();
index 6a813e012d1dd0e46c5f21efc8364b72d7570614..177d474fe41250c9083b17599bce450a63bdb9bc 100644 (file)
@@ -20,6 +20,7 @@ DIR_SYMLINKS="
 
 MVWITHLIBS="
 @SYSTEM_RECOVERY_LIBEXEC_DIR@/recovery-init
+@SYSTEM_RECOVERY_DATA_DIR@/system-recovery.cfg
 @INITRD_RECOVERY_LIBEXEC_DIR@/minireboot
 m4_ifdef(`RECOVERY_GUI',
 `/usr/share/system-recovery/res/images/font.png
index 48866ede7e2c17027d83e558300407d001c56b7f..347ca9879625b4bf355813516c32d485418f9944 100644 (file)
@@ -23,6 +23,7 @@
 #include <signal.h>
 #include <unistd.h>
 #include <stdbool.h>
+#include <libconfig.h>
 #include <stdlib.h>
 
 #include <sys/stat.h>
@@ -87,6 +88,9 @@ void run_factory_reset(void)
 
 int main(void)
 {
+       config_t cfg;
+       int ret;
+
        LOGD("[main] recovery started.\n");
 #ifdef HAVE_TDM
        /* These should be set externally */
@@ -102,7 +106,14 @@ int main(void)
        setenv("TBM_DISPLAY_SERVER", "1", 1);
 #endif
 
-       if (!recovery_rui_init()) {
+       config_init(&cfg);
+       ret = config_read_file(&cfg, SYSTEM_RECOVERY_CONFIG_FILE);
+       if (ret == CONFIG_FALSE) {
+               LOGD("Can't read config file");
+               return 1;
+       }
+#ifdef RECOVERY_GUI
+       if (!recovery_rui_init(&cfg)) {
                LOGD("Can't initialize GUI.\n");
                return 1;
        }
@@ -121,6 +132,9 @@ int main(void)
 
        ev_exit();
        recovery_rui_exit();
+#else
+       // XXX: run default action
+#endif
        LOGD("[main] recovery finished.\n");
        return 0;
 }
index dbf4b914f76b2489ff2221f5db50df57f8e89035..09b0371b0d744de4052e3c9eac7250b3bd8be77b 100644 (file)
  * limitations under the License.
  */
 
+#include <libconfig.h>
 #include <string.h>
 #include <stdlib.h>
 #include <stdbool.h>
+#include <errno.h>
 
 #include "rui.h"
 #include "common.h"
 #include "config.h"
 #include "rui-menu.h"
 #include "graphics.h"
+#include "log.h"
 #include "rui-image.h"
 #include "rui-ruler.h"
 #include "input-events.h"
 #include "rui-progress-bar.h"
 #include "recovery-rui-skin.h"
 
-static rui_image rui_images[] = {
-       [RECOVERY_RUI_IMAGE_BACKGROUND_DEFAULT] = {
-               .fname          = SYSTEM_RECOVERY_IMAGE_DIR "/warning.png",
-               .c_bg           = RUI_COLOR_BACKGROUND,
-               .align_hor      = GR_ALIGN_CENTER,
-               .align_ver      = GR_ALIGN_BOTTOM,
-               .offset_x       = 0,
-               .offset_y       = 0,
-               .img_type       = GR_WITH_ALPHA,
-               .surface        = NULL
-       },
-       [RECOVERY_RUI_IMAGE_MENU_TITLE] = {
-               .fname          = SYSTEM_RECOVERY_IMAGE_DIR "/menu-title.png",
-               .c_bg           = RUI_COLOR_TITLE,
-               .align_hor      = GR_ALIGN_CENTER,
-               .align_ver      = GR_ALIGN_TOP,
-               .offset_x       = 0,
-               .offset_y       = 20,
-               .img_type       = GR_WITH_ALPHA,
-               .surface        = NULL
+void recovery_rui_input_callback(user_action action, user_action_type action_type)
+{
+       int need_repaint = 1;
+       rui_screen *cs;
+
+       /* We interested only in button downs, long presses and idle events */
+       if (action_type != ACTION_TYPE_BEGIN &&
+           action_type != ACTION_TYPE_LONGPRESS &&
+           action_type != ACTION_TYPE_IDLE)
+               return;
+
+       cs = get_current_screen();
+       if (action == ACTION_DOWN && cs->menu)
+               rui_menu_cursor_down(cs->menu);
+       else if (action == ACTION_UP && cs->menu)
+               rui_menu_cursor_up(cs->menu);
+       else if (get_current_screen_id() == RECOVERY_RUI_SCREEN_FACTORY_RUN &&
+                action == ACTION_CONFIRM &&
+                action_type == ACTION_TYPE_LONGPRESS)
+               sys_power_reboot();
+       else if ((action == ACTION_CONFIRM || action == ACTION_HOME) &&
+                cs->menu)
+               rui_menu_action_run(cs->menu);
+       else if (action == ACTION_BACK)
+               rui_screen_switch(RUI_SCREEN_BACK);
+       else if (action != ACTION_NONE || action_type != ACTION_TYPE_IDLE ||
+                !cs->animations)
+               need_repaint = 0;
+
+       if (need_repaint)
+               rui_draw();
+}
+
+static struct {
+       const char **rui_screens;
+       const char **rui_menus;
+       const char **rui_animations;
+       const char **rui_images;
+       const char **rui_colors;
+       const char **rui_screen_styles;
+       const char **rui_menu_styles;
+       const char **rui_ruler_styles;
+       const char **rui_rulers;
+       const char **rui_description_styles;
+       const char **rui_descriptions;
+} rui_config_labels;
+
+static rui_screen *rui_screens = NULL;
+static rui_menu *rui_menus = NULL;
+static rui_screen_style *rui_screen_styles = NULL;
+static rui_menu_style *rui_menu_styles = NULL;
+static rui_ruler_style *rui_ruler_styles = NULL;
+static rui_animation *rui_animations = NULL;
+static rui_image *rui_images = NULL;
+static color *rui_colors = NULL;
+static rui_ruler **rui_rulers = NULL;
+static rui_description_style *rui_description_styles = NULL;
+static rui_description *rui_descriptions = NULL;
+
+/* naive search */
+int find_string(const char **list, const char *s)
+{
+       int i;
+
+       if (!list)
+               return -EINVAL;
+
+       for (i = 0; list[i]; ++i)
+               if (strcmp(list[i], s) == 0)
+                       return i;
+
+       return -ENOENT;
+}
+
+static inline int _rui_lookup_setting(config_setting_t *root, const char **labels, const char *name)
+{
+       const char *value;
+       int ret;
+
+       ret = config_setting_lookup_string(root, name, &value);
+       if (ret == CONFIG_FALSE)
+               return -1;
+
+       return find_string(labels, value);
+}
+
+#define rui_lookup_setting(root, list, out, field) do {                        \
+               int _idx = _rui_lookup_setting(root, rui_config_labels.list, #field); \
+               if (_idx < 0 || !list) {                                \
+                       (out)->field = NULL;                            \
+                       log_deb("Could not find setting %s.%s", #out, #field); \
+               } else                                                  \
+                       (out)->field = &list[_idx];                     \
+       } while (0)
+
+#define rui_lookup_setting_value(root, list, out, field) do {          \
+               int _idx = _rui_lookup_setting(root, rui_config_labels.list, #field); \
+               if (_idx < 0 || !list)                                  \
+                       log_deb("Could not find setting %s.%s", #out, #field); \
+               else                                                    \
+                       out->field = list[_idx];                        \
+       } while (0)
+
+static inline int ascii_hex(char c)
+{
+       switch (c) {
+       case '0' ... '9':
+               return c - '0';
+       case 'A' ... 'F':
+               return c - 'A' + 10;
+       case 'a' ... 'f':
+               return c - 'a' + 10;
        }
-};
 
-static rui_animation rui_animations[] = {
-       [RECOVERY_RUI_ANIMATION_WORKING] = {
-               .fname          = SYSTEM_RECOVERY_IMAGE_DIR "/tizen-anim.png",
-               .c_bg           = RUI_COLOR_BACKGROUND,
-               .align_hor      = GR_ALIGN_CENTER,
-               .align_ver      = GR_ALIGN_MIDDLE,
-               .offset_x       = 0,
-               .offset_y       = 0,
-               .frames_num     = 0,
-               .current_frame  = 0,
-               .img_type       = GR_WITH_ALPHA,
-               .surfaces       = NULL
+       return 0;
+}
+
+static inline char get_hex_byte(const char *s)
+{
+       return 16 * ascii_hex(s[0]) + ascii_hex(s[1]);
+}
+
+static int color_entry_parse(config_setting_t *root, void *data)
+{
+       color *c = data;
+       const char *str;
+
+       str = config_setting_get_string(root);
+       if (!str)
+               return -ENOENT;
+
+       if (strlen(str) == 9 && str[0] == '#') {
+               c->r = get_hex_byte(str + 1);
+               c->g = get_hex_byte(str + 3);
+               c->b = get_hex_byte(str + 5);
+               c->a = get_hex_byte(str + 7);
+
+               return 0;
        }
+
+       return -ENOTSUP;
+}
+
+struct str2int_map {
+       const char *key;
+       int value;
 };
 
-static rui_menu_style rui_menu_common_style = {
-       .item_height            = RUI_MENU_ITEM_HEIGHT,
-       .item_spacing           = RUI_MENU_ITEM_SPACING,
-       .text_pos_x             = RUI_MENU_TEXT_POS_X,
-       .c_bg_selected          = RUI_COLOR_MENU_BG_SELECTED,
-       .c_bg_unselected        = RUI_COLOR_MENU_BG_UNSELECTED,
-       .c_text_selected        = RUI_COLOR_MENU_TEXT_SELECTED,
-       .c_text_unselected      = RUI_COLOR_MENU_TEXT_UNSELECTED
+static int map_find(const char *key, struct str2int_map *map)
+{
+       int i;
+
+       for (i = 0; map[i].key; ++i)
+               if (strcmp(key, map[i].key) == 0)
+                       return map[i].value;
+
+       return -1;
+}
+
+static struct str2int_map align_hor_map[] = {
+       {"left", GR_ALIGN_LEFT},
+       {"center", GR_ALIGN_CENTER},
+       {"right", GR_ALIGN_RIGHT},
+       {NULL, 0}
 };
 
-static const char *rui_main_menu_items[] = {
-       "Reboot system now",
-       "Safe mode",
-       "Phone reinitialization",
+static struct str2int_map align_ver_map[] = {
+       {"top", GR_ALIGN_TOP},
+       {"middle", GR_ALIGN_MIDDLE},
+       {"bottom", GR_ALIGN_BOTTOM},
+       {NULL, 0}
 };
 
-static const char *rui_confirm_menu_items[] = {
-       "Yes",
-       "No"
+static struct str2int_map img_type_map[] = {
+       {"no-alpha", GR_WITHOUT_ALPHA},
+       {"alpha", GR_WITH_ALPHA},
+       {NULL, 0}
 };
 
-static rui_menu_action rui_main_menu_actions[] = {
-       {
-               .screen_switch_to       = RECOVERY_RUI_SCREEN_REBOOT,
-               .action_handler         = NULL
-       }, {
-               .screen_switch_to       = RECOVERY_RUI_SCREEN_SAFE,
-               .action_handler         = NULL
-       }, {
-               .screen_switch_to       = RECOVERY_RUI_SCREEN_FACTORY,
-               .action_handler         = NULL
+static int image_entry_parse(config_setting_t *root, void *data)
+{
+       rui_image *image = data;
+       const char *value;
+       int ret;
+
+       ret = config_setting_lookup_string(root, "fname", &image->fname);
+       if (ret == CONFIG_FALSE)
+               return -1;
+
+       rui_lookup_setting_value(root, rui_colors, image, c_bg);
+
+       ret = config_setting_lookup_string(root, "align_hor", &value);
+       image->align_hor = map_find(value, align_hor_map);
+
+       ret = config_setting_lookup_string(root, "align_ver", &value);
+       image->align_ver = map_find(value, align_ver_map);
+
+       config_setting_lookup_int(root, "offset_x", &image->offset_x);
+       config_setting_lookup_int(root, "offset_y", &image->offset_y);
+
+       ret = config_setting_lookup_string(root, "img_type", &value);
+       image->img_type = map_find(value, img_type_map);
+
+       image->surface = NULL;
+
+       return 0;
+}
+
+static int animation_entry_parse(config_setting_t *root, void *data)
+{
+       rui_animation *animation = data;
+       const char *value;
+       int ret;
+
+       ret = config_setting_lookup_string(root, "fname", &animation->fname);
+       if (ret == CONFIG_FALSE)
+               return -1;
+
+       rui_lookup_setting_value(root, rui_colors, animation, c_bg);
+
+       ret = config_setting_lookup_string(root, "align_hor", &value);
+       animation->align_hor = map_find(value, align_hor_map);
+
+       ret = config_setting_lookup_string(root, "align_ver", &value);
+       animation->align_ver = map_find(value, align_ver_map);
+
+       config_setting_lookup_int(root, "offset_x", &animation->offset_x);
+       config_setting_lookup_int(root, "offset_y", &animation->offset_y);
+       config_setting_lookup_int(root, "frames_num", &animation->frames_num);
+       config_setting_lookup_int(root, "icurrent_frame", &animation->frames_num);
+
+       ret = config_setting_lookup_string(root, "img_type", &value);
+       animation->img_type = map_find(value, img_type_map);
+
+       animation->surfaces = NULL;
+
+       return 0;
+}
+
+static int get_screen_id(config_setting_t *root, const char *key)
+{
+       int ret;
+       static const char *special_labels[] = {
+               "",
+               "CURRENT",
+               "BACK",
+       };
+
+       ret = _rui_lookup_setting(root,
+                                 rui_config_labels.rui_screens, key);
+       if (ret != -ENOENT)
+               return ret;
+
+       ret = _rui_lookup_setting(root, special_labels, key);
+       if (ret < 0) {
+               log_err("Could not get screen id");
+               return RUI_SCREEN_CURRENT;
+       } else {
+               return -ret;
        }
-};
+}
 
-ASSERT_ARRAYS_EQUAL_LENGTH(rui_main_menu_actions, rui_main_menu_items);
-
-static rui_menu rui_main_menu = {
-       .pos_x          = RUI_MAIN_MENU_POS_X,
-       .pos_y          = RUI_MAIN_MENU_POS_Y,
-       .style          = &rui_menu_common_style,
-       .items          = rui_main_menu_items,
-       .items_num      = ARRAY_SIZE(rui_main_menu_items),
-       .item_selected  = 0,
-       .item_default   = RUI_MENU_ITEM_DO_NOT_CHANGE,
-       .actions        = rui_main_menu_actions
-};
+static int menu_entry_parse(config_setting_t *root, void *data)
+{
+       config_setting_t *actions, *node;
+       rui_menu *menu = data;
+       int i;
+       int ret;
+
+       rui_lookup_setting(root, rui_menu_styles, menu, style);
+
+       config_setting_lookup_int(root, "pos_x", &menu->pos_x);
+       config_setting_lookup_int(root, "pos_y", &menu->pos_y);
+       config_setting_lookup_int(root, "item_selected", &menu->item_selected);
+       config_setting_lookup_int(root, "item_default", &menu->item_default);
+
+       actions = config_setting_get_member(root, "actions");
+       if (!actions)
+               return 0;
+
+       menu->items_num = config_setting_length(actions);
+       menu->items = calloc(menu->items_num, sizeof(*menu->items));
+       menu->actions = calloc(menu->items_num, sizeof(*menu->actions));
+       if (!menu->items || !menu->actions) {
+               ret = -ENOMEM;
+               goto err;
+       }
 
-static rui_menu_action rui_reboot_menu_actions[] = {
-       {
-               .screen_switch_to       = RUI_SCREEN_CURRENT,
-               .action_handler         = sys_power_reboot
-       }, {
-               .screen_switch_to       = RUI_SCREEN_BACK,
-               .action_handler         = NULL
+       for (i = 0; i < menu->items_num; ++i) {
+               node = config_setting_get_elem(actions, i);
+               if (!node) {
+                       log_err("Could not get next setting");
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               config_setting_lookup_string(node, "label", &menu->items[i]);
+               menu->actions[i].screen_switch_to = get_screen_id(node, "screen_switch_to");
+               config_setting_lookup_string(node, "handler", &menu->actions[i].action_handler);
        }
-};
 
-ASSERT_ARRAYS_EQUAL_LENGTH(rui_reboot_menu_actions, rui_confirm_menu_items);
-
-static rui_menu rui_reboot_menu = {
-       .pos_x          = RUI_REBOOT_MENU_POS_X,
-       .pos_y          = RUI_REBOOT_MENU_POS_Y,
-       .style          = &rui_menu_common_style,
-       .items          = rui_confirm_menu_items,
-       .items_num      = ARRAY_SIZE(rui_confirm_menu_items),
-       .item_selected  = 1,
-       .item_default   = 1,
-       .actions        = rui_reboot_menu_actions
-};
+       return 0;
+
+err:
+       free(menu->items);
+       free(menu->actions);
+       return ret;
+}
+
+static int description_style_entry_parse(config_setting_t *root, void *data)
+{
+       rui_description_style *style = data;
+       rui_lookup_setting_value(root, rui_colors, style, c_title);
+       rui_lookup_setting_value(root, rui_colors, style, c_text);
+
+       return 0;
+}
 
-static rui_menu_action rui_safe_menu_actions[] = {
-       {
-               .screen_switch_to       = RUI_SCREEN_CURRENT,
-               .action_handler         = boot_safe_mode
-       }, {
-               .screen_switch_to       = RUI_SCREEN_BACK,
-               .action_handler         = NULL
+static int description_entry_parse(config_setting_t *root, void *data)
+{
+       rui_description *desc = data;
+
+       config_setting_lookup_int(root, "pos_x", &desc->pos_x);
+       config_setting_lookup_int(root, "pos_y", &desc->pos_y);
+       rui_lookup_setting(root, rui_description_styles, desc, style);
+       config_setting_lookup_string(root, "title", &desc->title);
+       config_setting_lookup_string(root, "text", &desc->text);
+
+       return 0;
+}
+
+static int labels_list_parse(config_setting_t *root, int **out,
+                            const char *name, const char **labels)
+{
+       int i;
+       int num;
+       int *list;
+       config_setting_t *elem, *node;
+       const char *value;
+
+       node = config_setting_get_member(root, name);
+       if (!node)
+               return 0;
+
+       num = config_setting_length(node);
+       if (num < 0)
+               return -EINVAL;
+
+       list = calloc(num + 1, sizeof(*list));
+       if (!list)
+               return -ENOMEM;
+
+       for (i = 0; i < num; ++i) {
+               elem = config_setting_get_elem(node, i);
+               value = config_setting_get_string(elem);
+               list[i] = find_string(labels, value);
        }
-};
 
-ASSERT_ARRAYS_EQUAL_LENGTH(rui_safe_menu_actions, rui_confirm_menu_items);
-
-static rui_menu rui_safe_menu = {
-       .pos_x          = RUI_SAFE_MENU_POS_X,
-       .pos_y          = RUI_SAFE_MENU_POS_Y,
-       .style          = &rui_menu_common_style,
-       .items          = rui_confirm_menu_items,
-       .items_num      = ARRAY_SIZE(rui_confirm_menu_items),
-       .item_selected  = 1,
-       .item_default   = 1,
-       .actions        = rui_safe_menu_actions
-};
+       list[num] = -1;
+
+       *out = list;
+       return 0;
+}
+
+static int screen_entry_parse(config_setting_t *root, void *data)
+{
+       rui_screen *screen = data;
 
-static rui_menu_action rui_factory_menu_actions[] = {
-       {
-               .screen_switch_to       = RECOVERY_RUI_SCREEN_FACTORY_RUN,
-               .action_handler         = run_factory_reset
-       }, {
-               .screen_switch_to       = RUI_SCREEN_BACK,
-               .action_handler         = NULL
+       rui_lookup_setting(root, rui_screen_styles, screen, style);
+       rui_lookup_setting(root, rui_menus, screen, menu);
+       rui_lookup_setting_value(root, rui_rulers, screen, rulers);
+       rui_lookup_setting(root, rui_descriptions, screen, description);
+
+       labels_list_parse(root, &screen->images, "images",
+                         rui_config_labels.rui_images);
+       labels_list_parse(root, &screen->animations, "animations",
+                         rui_config_labels.rui_animations);
+
+       screen->screen_back = get_screen_id(root, "screen_back");
+
+       /*
+         screen->progress_bar = NULL;
+         screen->on_enter = NULL;
+         screen->draw = NULL;
+       */
+
+       return 0;
+}
+
+static int ruler_entry_parse(config_setting_t *root, void *data)
+{
+       rui_ruler *ruler = *(rui_ruler **)data;
+       config_setting_t *node;
+       int num;
+       int i;
+
+       num = config_setting_length(root);
+       if (num < 0)
+               return -EINVAL;
+
+       for (i = 0; i < num; ++i) {
+               node = config_setting_get_elem(root, i);
+               config_setting_lookup_int(node, "pos_x", &ruler[i].pos_x);
+               config_setting_lookup_int(node, "pos_y", &ruler[i].pos_y);
+               config_setting_lookup_int(node, "height", &ruler[i].height);
+               rui_lookup_setting(node, rui_ruler_styles, &ruler[i], style);
        }
-};
 
-ASSERT_ARRAYS_EQUAL_LENGTH(rui_factory_menu_actions, rui_confirm_menu_items);
-
-static rui_menu rui_factory_menu = {
-       .pos_x          = RUI_FACTORY_MENU_POS_X,
-       .pos_y          = RUI_FACTORY_MENU_POS_Y,
-       .style          = &rui_menu_common_style,
-       .items          = rui_confirm_menu_items,
-       .items_num      = ARRAY_SIZE(rui_confirm_menu_items),
-       .item_selected  = 1,
-       .item_default   = 1,
-       .actions        = rui_factory_menu_actions
-};
+       return 0;
+}
 
-static rui_description_style rui_description_common_style = {
-       .c_title        = RUI_COLOR_DESCRIPTION_TITLE,
-       .c_text         = RUI_COLOR_DESCRIPTION_TEXT
-};
+static int ruler_entry_init(config_setting_t *root, void *data)
+{
+       rui_ruler **out = data;
+       rui_ruler *ruler;
+       int num;
 
-static rui_description rui_main_screen_description = {
-       .pos_x          = RUI_MAIN_SCREEN_DESCRIPTION_POS_X,
-       .pos_y          = RUI_MAIN_SCREEN_DESCRIPTION_POS_Y,
-       .style          = &rui_description_common_style,
-       .title          = "Controls:",
-       .text           = "Volume Up/Down to move menu cursor\n"
-               "Power button to select"
-};
+       num = config_setting_length(root);
+       if (num < 0)
+               return -EINVAL;
 
-static rui_description rui_reboot_screen_description = {
-       .pos_x          = RUI_REBOOT_SCREEN_DESCRIPTION_POS_X,
-       .pos_y          = RUI_REBOOT_SCREEN_DESCRIPTION_POS_Y,
-       .style          = &rui_description_common_style,
-       .title          = "The phone will be restarted.",
-       .text           = "Continue?"
-};
+       ruler = calloc(num + 1, sizeof(*ruler));
+       if (!ruler)
+               return -ENOMEM;
 
-static rui_description rui_safe_screen_description = {
-       .pos_x          = RUI_SAFE_SCREEN_DESCRIPTION_POS_X,
-       .pos_y          = RUI_SAFE_SCREEN_DESCRIPTION_POS_Y,
-       .style          = &rui_description_common_style,
-       .title          = "Safe mode:",
-       .text           = "The phone will be started in safe mode.\n"
-               "Home screen will be changed to default\n"
-               "setting and just allow a user to use\n"
-               "only preloaded applications.\n"
-               "Continue?"
-};
+       *out = ruler;
+       return 0;
+}
 
-static rui_description rui_factory_screen_description = {
-       .pos_x          = RUI_FACTORY_SCREEN_DESCRIPTION_POS_X,
-       .pos_y          = RUI_FACTORY_SCREEN_DESCRIPTION_POS_Y,
-       .style          = &rui_description_common_style,
-       .title          = "Factory reset (except SD-card)",
-       .text           = "This will erase all data from your\n"
-               "phone's internal storage, including\n"
-               "settings of downloaded and preloaded\n"
-               "applications and system configuration.\n"
-               "Continue?"
-};
+static int screen_style_entry_parse(config_setting_t *root, void *data)
+{
+       rui_screen_style *style = data;
 
-static rui_description rui_factory_run_screen_description = {
-       .pos_x          = RUI_FACTORY_RUN_SCREEN_DESCRIPTION_POS_X,
-       .pos_y          = RUI_FACTORY_RUN_SCREEN_DESCRIPTION_POS_Y,
-       .style          = &rui_description_common_style,
-       .title          = "Restoring settings to factory default.",
-       .text           = "Please wait. Do not turn off.\n"
-               "(Hold power button for 3 seconds\n"
-               "to reboot the device. Not recommended.)"
-};
+       rui_lookup_setting_value(root, rui_colors, style, c_background);
 
-static rui_ruler_style rui_ruler_common_style = {
-       .c_ruler        = RUI_COLOR_RULER
-};
+       return 0;
+}
+
+static int menu_style_entry_parse(config_setting_t *root, void *data)
+{
+       rui_menu_style *style = data;
+
+       config_setting_lookup_int(root, "item_height", &style->item_height);
+       config_setting_lookup_int(root, "item_spacing", &style->item_spacing);
+       config_setting_lookup_int(root, "text_pos_x", &style->text_pos_x);
+       rui_lookup_setting_value(root, rui_colors, style, c_bg_selected);
+       rui_lookup_setting_value(root, rui_colors, style, c_bg_unselected);
+       rui_lookup_setting_value(root, rui_colors, style, c_text_selected);
+       rui_lookup_setting_value(root, rui_colors, style, c_text_unselected);
 
-static rui_ruler rui_main_screen_rulers[] = {
-       {       /* After menu title */
-               .pos_x  = RUI_RULER_TOP_POS_X,
-               .pos_y  = RUI_RULER_TOP_POS_Y,
-               .height = RUI_RULER_HEIGHT,
-               .style  = &rui_ruler_common_style
-       }, {    /* After main menu */
-               .pos_x  = RUI_RULER_TOP_POS_X,
-               .pos_y  = RUI_MAIN_SCREEN_RULER_POS_Y,
-               .height = RUI_RULER_HEIGHT,
-               .style  = &rui_ruler_common_style
-       }, {    /* End marker */
-               .pos_x  = 0,
-               .pos_y  = 0,
-               .height = 0,
-               .style  = NULL
+       return 0;
+}
+
+static int ruler_style_entry_parse(config_setting_t *root, void *data)
+{
+       rui_ruler_style *style = data;
+
+       rui_lookup_setting_value(root, rui_colors, style, c_ruler);
+
+       return 0;
+}
+
+static int rui_config_group_init(config_t *cfg, const char *group_name,
+                                int (*entry_init)(config_setting_t *root, void *out),
+                                void **out, size_t entry_size, const char ***labels)
+{
+       int num, i;
+       config_setting_t *root, *node;
+       char *data;
+       const char **labels_data;
+       int ret;
+
+       root = config_lookup(cfg, group_name);
+       if (!root) {
+               log_err("Could not find %s group in config", group_name);
+               return -ENOENT;
        }
-};
 
-/* Both for reboot and safe mode screens */
-static rui_ruler rui_confirm_screens_rulers[] = {
-       {       /* After menu title */
-               .pos_x  = RUI_RULER_TOP_POS_X,
-               .pos_y  = RUI_RULER_TOP_POS_Y,
-               .height = RUI_RULER_HEIGHT,
-               .style  = &rui_ruler_common_style
-       }, {    /* End marker */
-               .pos_x  = 0,
-               .pos_y  = 0,
-               .height = 0,
-               .style  = NULL
+       num = config_setting_length(root);
+       if (num <= 0)
+               return 0;
+
+       data = calloc(num, entry_size);
+       labels_data = calloc(num + 1, sizeof(*labels_data));
+       if (!data || !labels_data) {
+               log_err("Could not allocate memory");
+               ret = -ENOMEM;
+               goto err;
        }
-};
 
-static rui_screen_style rui_screen_common_style = {
-       .c_background   = RUI_COLOR_BACKGROUND
-};
+       for (i = 0; i < num; ++i) {
+               node = config_setting_get_elem(root, i);
+               if (!node) {
+                       log_err("Could not get next setting");
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               labels_data[i] = config_setting_name(node);
+
+               if (entry_init) {
+                       ret = entry_init(node, data + i * entry_size);
+                       if (ret < 0)
+                               goto err;
+               }
+       }
 
-static int rui_common_screen_images[] = {
-       RECOVERY_RUI_IMAGE_BACKGROUND_DEFAULT,
-       RECOVERY_RUI_IMAGE_MENU_TITLE,
-       RUI_IMAGE_NONE /* Stop element */
-};
+       *out = data;
+       *labels = labels_data;
+       return num;
 
-static int rui_common_run_screen_images[] = {
-       RECOVERY_RUI_IMAGE_MENU_TITLE,
-       RUI_IMAGE_NONE /* Stop element */
-};
+err:
+       free(data);
+       free(labels_data);
+       return ret;
+}
 
-static int rui_factory_run_screen_animations[] = {
-       RECOVERY_RUI_ANIMATION_WORKING,
-       RUI_ANIMATION_NONE /* Stop element */
-};
+static int rui_config_group_parse(config_t *cfg, const char *group_name,
+                                 int (*entry_parse)(config_setting_t *root, void *out),
+                                 char *data, size_t entry_size)
+{
+       int num, i;
+       config_setting_t *root, *node;
+       int ret;
+
+       root = config_lookup(cfg, group_name);
+       if (!root) {
+               log_err("Could not find %s group in config", group_name);
+               return -ENOENT;
+       }
 
-static rui_screen rui_screens[] = {
-       [RECOVERY_RUI_SCREEN_MAIN] = {
-               .style                  = &rui_screen_common_style,
-               .menu                   = &rui_main_menu,
-               .description            = &rui_main_screen_description,
-               .rulers                 = rui_main_screen_rulers,
-               .progress_bar           = NULL,
-               .images                 = rui_common_screen_images,
-               .animations             = NULL,
-               .on_enter               = NULL,
-               .draw                   = NULL,
-               .screen_back            = RUI_SCREEN_CURRENT
-       },
-       [RECOVERY_RUI_SCREEN_REBOOT] = {
-               .style                  = &rui_screen_common_style,
-               .menu                   = &rui_reboot_menu,
-               .description            = &rui_reboot_screen_description,
-               .rulers                 = rui_confirm_screens_rulers,
-               .progress_bar           = NULL,
-               .images                 = rui_common_screen_images,
-               .animations             = NULL,
-               .on_enter               = NULL,
-               .draw                   = NULL,
-               .screen_back            = RECOVERY_RUI_SCREEN_MAIN
-       },
-       [RECOVERY_RUI_SCREEN_SAFE] = {
-               .style                  = &rui_screen_common_style,
-               .menu                   = &rui_safe_menu,
-               .description            = &rui_safe_screen_description,
-               .rulers                 = rui_confirm_screens_rulers,
-               .progress_bar           = NULL,
-               .images                 = rui_common_screen_images,
-               .animations             = NULL,
-               .on_enter               = NULL,
-               .draw                   = NULL,
-               .screen_back            = RECOVERY_RUI_SCREEN_MAIN
-       },
-       [RECOVERY_RUI_SCREEN_FACTORY] = {
-               .style                  = &rui_screen_common_style,
-               .menu                   = &rui_factory_menu,
-               .description            = &rui_factory_screen_description,
-               .rulers                 = rui_confirm_screens_rulers,
-               .progress_bar           = NULL,
-               .images                 = rui_common_screen_images,
-               .animations             = NULL,
-               .on_enter               = NULL,
-               .draw                   = NULL,
-               .screen_back            = RECOVERY_RUI_SCREEN_MAIN
-       },
-       [RECOVERY_RUI_SCREEN_FACTORY_RUN] = {
-               .style                  = &rui_screen_common_style,
-               .menu                   = NULL,
-               .description            = &rui_factory_run_screen_description,
-               .rulers                 = rui_confirm_screens_rulers,
-               .progress_bar           = NULL,
-               .images                 = rui_common_run_screen_images,
-               .animations             = rui_factory_run_screen_animations,
-               .on_enter               = NULL,
-               .draw                   = NULL,
-               .screen_back            = RUI_SCREEN_CURRENT
+       num = config_setting_length(root);
+       if (num <= 0)
+               return 0;
+
+       for (i = 0; i < num; ++i) {
+               node = config_setting_get_elem(root, i);
+               if (!node) {
+                       log_err("Could not get next setting");
+                       ret = -ENOMEM;
+                       goto err;
+               }
+
+               ret = entry_parse(node, data + i * entry_size);
+               if (ret < 0)
+                       goto err;
        }
-};
 
-void recovery_rui_input_callback(user_action action, user_action_type action_type)
+       return num;
+
+err:
+       return ret;
+}
+
+bool recovery_rui_init(config_t *cfg)
 {
-       int need_repaint = 1;
-       rui_screen *cs;
+       int main_screen_n = 0;
+       int i;
+
+#define DECLARE_GROUP(n, g, h) {               \
+               .name = n,                      \
+               .out = (void **)&g,             \
+               .entry_size = sizeof(*g),       \
+               .entry_init = NULL,             \
+               .entry_parse = h,               \
+               .labels = &rui_config_labels.g  \
+}
 
-       /* We interested only in button downs, long presses and idle events */
-       if (action_type != ACTION_TYPE_BEGIN &&
-                       action_type != ACTION_TYPE_LONGPRESS &&
-                       action_type != ACTION_TYPE_IDLE)
+#define DECLARE_GROUP_INIT(n, g, i, h) {       \
+               .name = n,                      \
+               .out = (void **)&g,             \
+               .entry_size = sizeof(*g),       \
+               .entry_init = i,                \
+               .entry_parse = h,               \
+               .labels = &rui_config_labels.g  \
+}
+
+       static struct {
+               const char *name;
+               void **out;
+               size_t entry_size;
+               int (*entry_init)(config_setting_t *root, void *out);
+               int (*entry_parse)(config_setting_t *root, void *out);
+               const char ***labels;
+
+               int num;
+       } groups[] = {
+               DECLARE_GROUP("screens", rui_screens, screen_entry_parse),
+               DECLARE_GROUP("images", rui_images, image_entry_parse),
+               DECLARE_GROUP("animations", rui_animations, animation_entry_parse),
+               DECLARE_GROUP("menus", rui_menus, menu_entry_parse),
+               DECLARE_GROUP("colors", rui_colors, color_entry_parse),
+               DECLARE_GROUP("menu_styles", rui_menu_styles, menu_style_entry_parse),
+               DECLARE_GROUP("screen_styles", rui_screen_styles, screen_style_entry_parse),
+               DECLARE_GROUP("ruler_styles", rui_ruler_styles, ruler_style_entry_parse),
+               DECLARE_GROUP_INIT("rulers", rui_rulers, ruler_entry_init, ruler_entry_parse),
+               DECLARE_GROUP("description_styles", rui_description_styles, description_style_entry_parse),
+               DECLARE_GROUP("descriptions", rui_descriptions, description_entry_parse),
+               {NULL}
+
+       };
+#undef DECLARE_GROUP
+#undef DECLARE_GROUP_INIT
+
+       for (i = 0; groups[i].name; ++i)
+               groups[i].num = rui_config_group_init(cfg, groups[i].name, groups[i].entry_init,
+                                                     groups[i].out, groups[i].entry_size, groups[i].labels);
+
+       for (i = 0; groups[i].name; ++i)
+               groups[i].num = rui_config_group_parse(cfg, groups[i].name, groups[i].entry_parse,
+                                                      *(char **)groups[i].out, groups[i].entry_size);
+
+       return rui_init(rui_screens, groups[0].num,
+                       main_screen_n,
+                       rui_images, groups[1].num,
+                       rui_animations, groups[2].num);
+}
+
+void cleanup_menus()
+{
+       int i;
+       if (!rui_menus)
                return;
 
-       cs = get_current_screen();
-       if (action == ACTION_DOWN && cs->menu)
-               rui_menu_cursor_down(cs->menu);
-       else if (action == ACTION_UP && cs->menu)
-               rui_menu_cursor_up(cs->menu);
-       else if (get_current_screen_id() == RECOVERY_RUI_SCREEN_FACTORY_RUN &&
-                       action == ACTION_CONFIRM &&
-                       action_type == ACTION_TYPE_LONGPRESS)
-               sys_power_reboot();
-       else if ((action == ACTION_CONFIRM || action == ACTION_HOME) &&
-                       cs->menu)
-               rui_menu_action_run(cs->menu);
-       else if (action == ACTION_BACK)
-               rui_screen_switch(RUI_SCREEN_BACK);
-       else if (action != ACTION_NONE || action_type != ACTION_TYPE_IDLE ||
-                       !cs->animations)
-               need_repaint = 0;
+       for (i = 0; rui_config_labels.rui_menus[i]; ++i) {
+               free(rui_menus[i].items);
+               free(rui_menus[i].actions);
+       }
+}
 
-       if (need_repaint)
-               rui_draw();
+void cleanup_rulers()
+{
+       int i;
+       if (!rui_rulers)
+               return;
+
+       for (i = 0; rui_config_labels.rui_rulers[i]; ++i)
+               free(rui_rulers[i]);
 }
 
-bool recovery_rui_init(void)
+void cleanup_screens()
 {
-       return rui_init(rui_screens, ARRAY_SIZE(rui_screens),
-                       RECOVERY_RUI_SCREEN_MAIN,
-                       rui_images, ARRAY_SIZE(rui_images),
-                       rui_animations, ARRAY_SIZE(rui_animations));
+       int i;
+       if (!rui_screens)
+               return;
+
+       for (i = 0; rui_config_labels.rui_screens[i]; ++i)
+               free(rui_screens[i].images);
 }
 
 void recovery_rui_exit(void)
 {
        rui_exit();
+
+       cleanup_screens();
+       free(rui_screens);
+       cleanup_menus();
+       free(rui_menus);
+       free(rui_screen_styles);
+       free(rui_menu_styles);
+       free(rui_ruler_styles);
+       free(rui_animations);
+       free(rui_images);
+       free(rui_colors);
+       cleanup_rulers();
+       free(rui_rulers);
+       free(rui_descriptions);
+
+       free(rui_config_labels.rui_screens);
+       free(rui_config_labels.rui_menus);
+       free(rui_config_labels.rui_screen_styles);
+       free(rui_config_labels.rui_menu_styles);
+       free(rui_config_labels.rui_ruler_styles);
+       free(rui_config_labels.rui_animations);
+       free(rui_config_labels.rui_images);
+       free(rui_config_labels.rui_colors);
+       free(rui_config_labels.rui_rulers);
+       free(rui_config_labels.rui_descriptions);
 }
diff --git a/src/system-recovery/system-recovery.cfg.m4.in b/src/system-recovery/system-recovery.cfg.m4.in
new file mode 100644 (file)
index 0000000..531c1c9
--- /dev/null
@@ -0,0 +1,278 @@
+// -*- mode: conf; indent-tabs-mode: nil -*-
+
+m4_define(`confirm_action',`({
+            label = "Yes";
+            handler = "$1";
+        },{
+            label = "No";
+            screen_switch_to = "BACK";
+        })')m4_dnl
+headless_action = "factory-reset";
+
+colors = {
+    background = "#000000ff";
+    title = "#1bc7ccff";
+    ruler = "#1bc7ccff";
+    white = "#ffffffff";
+};
+
+ruler_styles = {
+    common = {
+       c_ruler = "ruler";
+    };
+};
+
+menu_styles = {
+    common = {
+           item_height = 80;
+           item_spacing = 8;
+           text_pos_x = 15;
+           c_bg_selected = "title";
+           c_bg_unselected = "background";
+           c_text_selected = "white";
+           c_text_unselected = "white";
+    };
+};
+
+screen_styles = {
+    common = {
+       c_background = "background";
+    };
+};
+
+description_styles = {
+    common = {
+       c_title = "title";
+       c_text = "white";
+    };
+};
+
+rulers = {
+       main = (
+       {
+               pos_x = 0;
+               pos_y = 80;
+               height = 2;
+               style = "common";
+       }, {
+               pos_x = 0;
+               pos_y = 420;
+               height = 2;
+               style = "common";
+       });
+
+       confirm = (
+       {
+               pos_x = 0;
+               pos_y = 80;
+               height = 2;
+               style = "common";
+       });
+};
+
+images = {
+    background_default = {
+        fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/warning.png";
+        c_bg = "background"; // reference to colors
+        align_hor = "center";
+        align_ver = "bottom";
+        offset_x = 0;
+        offset_y = 0;
+        img_type = "alpha"; // alt: "no-alpha";
+        // surface = ;
+    };
+    menu_title = {
+        fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/menu-title.png";
+        c_bg = "title";
+        align_hor = "center";
+        align_ver = "top";
+        offset_x = 0;
+        offset_y = 20;
+        img_type = "no-alpha"; // alt: "no-alpha";
+        // surface = ;
+    };
+};
+
+animations = {
+    working = {
+        fname = "@SYSTEM_RECOVERY_IMAGE_DIR@/tizen-anim.png";
+        c_bg = "background";
+        align_hor = "center";
+        align_ver = "middle";
+        offset_x = 0;
+        offset_y = 0;
+        frames_num = 0;
+        current_frame = 0;
+        img_type = "no-alpha"; // alt: "no-alpha";
+        // surface = ;
+    };
+};
+
+menus = {
+    main = {
+        pos_x = 0; // use M4 macros
+        pos_y = 100; // use M4 macros
+        style = "common";
+        // item_selected = ;
+        // item_default = ;
+        actions = ({
+            label = "Reboot system now";
+            screen_switch_to = "reboot";
+            // handler = ;
+        },{
+            label = "Safe mode";
+            screen_switch_to = "safe";
+            // handler = ;
+        },{
+            label = "Phone reinitialisation";
+            screen_switch_to = "factory";
+            // handler = ;
+        });
+    };
+    reboot = {
+        pos_x = 0; // use M4 macros
+        pos_y = 480; // use M4 macros
+        style = "common";
+        item_selected = 1;
+        item_default = 1;
+        actions = confirm_action(`reboot -f');
+       exit_after_action = 1;
+    };
+    safe = {
+        pos_x = 0; // use M4 macros
+        pos_y = 480; // use M4 macros
+        style = "common";
+        item_selected = 1;
+        item_default = 1;
+        actions = confirm_action(`touch -f /opt/etc/.safeboot');
+       exit_after_action = 1;
+    };
+    factory = {
+        pos_x = 0; // use M4 macros
+        pos_y = 480; // use M4 macros
+        style = "common";
+        item_selected = 1;
+        item_default = 1;
+        actions = ({
+            label = "Yes";
+            screen_switch_to = "factory-run";
+            handler = "touch -f /opt/.factoryreset";
+        },{
+            label = "No";
+            screen_switch_to = "BACK";
+        });
+       exit_after_action = 1;
+    };
+};
+
+descriptions = {
+       main = {
+               pos_x = 15;
+               pos_y = 480;
+               style = "common";
+               title = "Controls:";
+               text = "Volume Up/Down to move menu cursor\n"
+                       "Power button to select";
+       };
+
+       reboot = {
+               pos_x = 15;
+               pos_y = 100;
+               title = "The phone will be restarted.";
+               text = "Continue?";
+               style = "common";
+       };
+
+       safe = {
+               pos_x = 15;
+               pos_y = 100;
+               title = "Safe mode:",
+               text = "The phone will be started in safe mode.\n"
+                       "Home screen will be changed to default\n"
+                       "setting and just allow a user to use\n"
+                       "only preloaded applications.\n"
+                       "Continue?";
+               style = "common";
+       };
+
+       factory = {
+               pos_x = 15;
+               pos_y = 100;
+               title = "Factory reset (except SD-card)";
+               text = "This will erase all data from your\n"
+                       "phone's internal storage, including\n"
+                       "settings of downloaded and preloaded\n"
+                       "applications and system configuration.\n"
+                       "Continue?";
+               style = "common";
+       };
+
+       factory-run = {
+               pos_x = 15;
+               pos_y = 100;
+               style = "common";
+               title = "Restoring settings to factory default.";
+               text = "Please wait. Do not turn off.\n"
+                       "(Hold power button for 3 seconds\n"
+                       "to reboot the device. Not recommended.)";
+       }
+};
+
+screens = {
+    main = {
+        style = "common";
+        menu = "main";
+        rulers = "main";
+       description = "main";
+        // progress_bar = ;
+        images = ("background_default", "menu_title");
+        // animations = ;
+        // on_enter = ;
+        // draw = ;
+        screen_back = "CURRENT";
+    };
+    reboot = {
+        style = "common";
+        menu = "reboot";
+        description = "reboot"
+        rulers = "confirm" ;
+        // progress_bar = ;
+        images = ("background_default", "menu_title");
+        // animations = ;
+        // on_enter = ;
+        // draw = ;
+        screen_back = "main";
+    };
+    safe = {
+        style = "common";
+        menu = "safe";
+        description = "safe";
+        rulers = "confirm";
+        // progress_bar = ;
+        images = ("background_default", "menu_title");
+        // animations = ;
+        // on_enter = ;
+        // draw = ;
+        screen_back = "main";
+    };
+    factory = {
+        style = "common";
+        menu = "factory";
+        description = "factory";
+        rulers = "confirm";
+        // progress_bar = ;
+        images = ("background_default", "menu_title");
+        // animations = ;
+        // on_enter = ;
+        // draw = ;
+        screen_back = "main";
+    };
+    factory-run = {
+        style = "common";
+        description = "factory-run";
+        rulers = "confirm";
+        images = ("background_default", "menu_title");
+        animations = ("working");
+        screen_back = "main";
+    };
+};
index 196763c18f41c44d550d97f295b24b8379713626..e267e0dd227cd22588e873e78c056b97fffe5a31 100644 (file)
@@ -18,6 +18,7 @@
 
 #pragma once
 
+#include <libconfig.h>
 #include <stdio.h>
 #include <stdbool.h>
 
@@ -61,7 +62,7 @@ void boot_safe_mode(void);
 void run_factory_reset(void);
 void sd_restore(void);
 
-bool recovery_rui_init(void);
+bool recovery_rui_init(config_t *cfg);
 void recovery_rui_exit(void);
 void recovery_rui_input_callback(user_action action,
                user_action_type action_type);