static enum themable_icons shortcut_menu_get_icon(int selected_item, void * data)
{
    (void)data;
    struct shortcut *sc = get_shortcut(selected_item);
    if (!sc)
        return Icon_NOICON;
    if (sc->icon == Icon_NOICON)
    {
        switch (sc->type)
        {
            case SHORTCUT_FILE:
                return filetype_get_icon(filetype_get_attr(sc->u.path));
            case SHORTCUT_BROWSER:
                return Icon_Folder;
            case SHORTCUT_SETTING:
                return Icon_Menu_setting;
            case SHORTCUT_DEBUGITEM:
                return Icon_Menu_functioncall;
            case SHORTCUT_PLAYLISTMENU:
                return Icon_Playlist;
            case SHORTCUT_SHUTDOWN:
                return Icon_System_menu;
            case SHORTCUT_TIME:
                return Icon_Menu_functioncall;
            default:
                break;
        }
    }
    return sc->icon;
}
static int shortcut_menu_speak_item(int selected_item, void * data)
{
    (void)data;
    struct shortcut *sc = get_shortcut(selected_item);
    if (sc && sc->talk_clip[0])
        talk_file(NULL, NULL, sc->talk_clip, NULL, NULL, false);
    return 0;
}
void shortcuts_add(enum shortcut_type type, const char* value)
{
    struct shortcut* sc = get_shortcut(shortcut_count++);
    if (!sc)
        return;
    init_shortcut(sc);
    sc->type = type;
    if (type == SHORTCUT_SETTING)
        sc->u.setting = (void*)value;
    else
        strlcpy(sc->u.path, value, MAX_PATH);
    if (first_idx_to_writeback < 0)
        first_idx_to_writeback = shortcut_count - 1;
    register_storage_idle_func(shortcuts_ata_idle_callback);
}
static const char * shortcut_menu_get_name(int selected_item, void * data,
                                           char * buffer, size_t buffer_len)
{
    (void)data;
    (void)buffer;
    (void)buffer_len;
    struct shortcut *sc = get_shortcut(selected_item);
    if (!sc)
        return "";
    if (sc->type == SHORTCUT_SETTING)
        return sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id));
    else if (sc->type == SHORTCUT_SEPARATOR || sc->type == SHORTCUT_TIME)
        return sc->name;
    else if (sc->type == SHORTCUT_SHUTDOWN && sc->name[0] == '\0')
    {
        /* No translation support as only soft_shutdown has LANG_SHUTDOWN defined */
        return type_strings[SHORTCUT_SHUTDOWN];
    }
    return sc->name[0] ? sc->name : sc->u.path;
}
static void shortcuts_ata_idle_callback(void* data)
{
    (void)data;
    int fd;
    char buf[MAX_PATH];
    int current_idx = first_idx_to_writeback;
    if (first_idx_to_writeback < 0)
        return;
    fd = open(SHORTCUTS_FILENAME, O_APPEND|O_RDWR|O_CREAT, 0644);
    if (fd < 0)
        return;
    while (current_idx < shortcut_count)
    {
        struct shortcut* sc = get_shortcut(current_idx++);
        const char *type;
        int len;
        if (!sc)
            break;
        type = type_strings[sc->type];
        len = snprintf(buf, MAX_PATH, "[shortcut]\ntype: %s\ndata: ", type);
        write(fd, buf, len);
        if (sc->type == SHORTCUT_SETTING)
            write(fd, sc->u.setting->cfg_name, strlen(sc->u.setting->cfg_name));
        else
            write(fd, sc->u.path, strlen(sc->u.path));
        write(fd, "\n\n", 2);
    }
    close(fd);
    if (first_idx_to_writeback == 0)
    {
        /* reload all shortcuts because we appended to the shortcuts file which
         * has not been read yet.
         */
         reset_shortcuts();
         shortcuts_init();
    }
    first_idx_to_writeback = -1;
}
Exemple #6
0
/* Read in a character, interpret it as a shortcut or toggle if
 * necessary, and return it.
 * Set ran_func to TRUE if we ran a function associated with a
 * shortcut key, and set finished to TRUE if we're done after running
 * or trying to run a function associated with a shortcut key.
 * refresh_func is the function we will call to refresh the edit window. */
int do_statusbar_input(bool *ran_func, bool *finished,
	void (*refresh_func)(void))
{
    int input;
	/* The character we read in. */
    static int *kbinput = NULL;
	/* The input buffer. */
    static size_t kbinput_len = 0;
	/* The length of the input buffer. */
    const sc *s;
    bool have_shortcut = FALSE;
    const subnfunc *f;

    *ran_func = FALSE;
    *finished = FALSE;

    /* Read in a character. */
    input = get_kbinput(bottomwin);

#ifndef NANO_TINY
    if (input == KEY_WINCH)
	return KEY_WINCH;
#endif

#ifndef DISABLE_MOUSE
    /* If we got a mouse click and it was on a shortcut, read in the
     * shortcut character. */
    if (func_key && input == KEY_MOUSE) {
	if (do_statusbar_mouse() == 1)
	    input = get_kbinput(bottomwin);
	else {
	    meta_key = FALSE;
	    func_key = FALSE;
	    input = ERR;
	}
    }
#endif

    /* Check for a shortcut in the current list. */
    s = get_shortcut(&input);

    /* If we got a shortcut from the current list, or a "universal"
     * statusbar prompt shortcut, set have_shortcut to TRUE. */
    have_shortcut = (s != NULL);

    /* If we got a non-high-bit control key, a meta key sequence, or a
     * function key, and it's not a shortcut or toggle, throw it out. */
    if (!have_shortcut) {
	if (is_ascii_cntrl_char(input) || meta_key || func_key) {
	    beep();
	    meta_key = FALSE;
	    func_key = FALSE;
	    input = ERR;
	}
    }

    /* If we got a character, and it isn't a shortcut or toggle,
     * it's a normal text character.  Display the warning if we're
     * in view mode, or add the character to the input buffer if
     * we're not. */
    if (input != ERR && !have_shortcut) {
	/* If we're using restricted mode, the filename isn't blank,
	 * and we're at the "Write File" prompt, disable text input. */
	if (!ISSET(RESTRICTED) || openfile->filename[0] == '\0' ||
		currmenu != MWRITEFILE) {
	    kbinput_len++;
	    kbinput = (int *)nrealloc(kbinput, kbinput_len * sizeof(int));
	    kbinput[kbinput_len - 1] = input;
	}
     }

    /* If we got a shortcut, or if there aren't any other characters
     * waiting after the one we read in, we need to display all the
     * characters in the input buffer if it isn't empty. */
    if (have_shortcut || get_key_buffer_len() == 0) {
	if (kbinput != NULL) {
	    /* Display all the characters in the input buffer at
	     * once, filtering out control characters. */
	    char *output = charalloc(kbinput_len + 1);
	    size_t i;
	    bool got_enter;
		/* Whether we got the Enter key. */

	    for (i = 0; i < kbinput_len; i++)
		output[i] = (char)kbinput[i];
	    output[i] = '\0';

	    do_statusbar_output(output, kbinput_len, &got_enter, FALSE);

	    free(output);

	    /* Empty the input buffer. */
	    kbinput_len = 0;
	    free(kbinput);
	    kbinput = NULL;
	}

	if (have_shortcut) {
	    if (s->scfunc == do_tab || s->scfunc == do_enter_void)
		;
	    else if (s->scfunc == total_refresh)
		total_statusbar_refresh(refresh_func);
	    else if (s->scfunc == do_cut_text_void) {
		/* If we're using restricted mode, the filename
		 * isn't blank, and we're at the "Write File"
		 * prompt, disable Cut. */
		if (!ISSET(RESTRICTED) || openfile->filename[0] ==
			'\0' || currmenu != MWRITEFILE)
		    do_statusbar_cut_text();
	    } else if (s->scfunc == do_left)
		do_statusbar_left();
	    else if (s->scfunc == do_right)
		do_statusbar_right();
#ifndef NANO_TINY
	    else if (s->scfunc == do_prev_word_void)
		do_statusbar_prev_word(FALSE);
	    else if (s->scfunc == do_next_word_void)
		do_statusbar_next_word(FALSE);
#endif
	    else if (s->scfunc == do_home)
		do_statusbar_home();
	    else if (s->scfunc == do_end)
		do_statusbar_end();
	    else if (s->scfunc == do_verbatim_input) {
		/* If we're using restricted mode, the filename
		 * isn't blank, and we're at the "Write File"
		 * prompt, disable verbatim input. */
		if (!ISSET(RESTRICTED) || currmenu != MWRITEFILE ||
			openfile->filename[0] == '\0') {
		    bool got_enter;
		    /* Whether we got the Enter key. */

		    do_statusbar_verbatim_input(&got_enter);

		    /* If we got the Enter key, remove it from the input
		     * buffer, set input to the key value for Enter, and
		     * set finished to TRUE to indicate that we're done. */
		    if (got_enter) {
			get_input(NULL, 1);
			input = sc_seq_or(do_enter_void, 0);
			*finished = TRUE;
		    }
		}
	    } else if (s->scfunc == do_delete) {
		/* If we're using restricted mode, the filename
		 * isn't blank, and we're at the "Write File"
		 * prompt, disable Delete. */
		if (!ISSET(RESTRICTED) || openfile->filename[0] ==
			'\0' || currmenu != MWRITEFILE)
		    do_statusbar_delete();
	    } else if (s->scfunc == do_backspace) {
		/* If we're using restricted mode, the filename
		 * isn't blank, and we're at the "Write File"
		 * prompt, disable Backspace. */
		if (!ISSET(RESTRICTED) || openfile->filename[0] ==
			'\0' || currmenu != MWRITEFILE)
		    do_statusbar_backspace();
	    } else {
		/* Handle any other shortcut in the current menu, setting
		 * ran_func to TRUE if we try to run their associated
		 * functions and setting finished to TRUE to indicate
		 * that we're done after running or trying to run their
		 * associated functions. */
		f = sctofunc((sc *) s);
		if (s->scfunc != NULL) {
		    *ran_func = TRUE;
		    if (f && (!ISSET(VIEW_MODE) || f->viewok) &&
				f->scfunc != do_gotolinecolumn_void)
			f->scfunc();
		}
		*finished = TRUE;
	    }
	}
    }

    return input;
}
Exemple #7
0
/* Get a string of input at the statusbar prompt.  This should only be
 * called from do_prompt(). */
const sc *get_prompt_string(int *actual, bool allow_tabs,
#ifndef DISABLE_TABCOMP
	bool allow_files,
#endif
	const char *curranswer,
	bool *meta_key, bool *func_key,
#ifndef NANO_TINY
	filestruct **history_list,
#endif
	void (*refresh_func)(void), int menu
#ifndef DISABLE_TABCOMP
	, bool *list
#endif
	)
{
    int kbinput = ERR;
    bool have_shortcut, ran_func, finished;
    size_t curranswer_len;
    const sc *s;
#ifndef DISABLE_TABCOMP
    bool tabbed = FALSE;
	/* Whether we've pressed Tab. */
#endif
#ifndef NANO_TINY
    char *history = NULL;
	/* The current history string. */
    char *magichistory = NULL;
	/* The temporary string typed at the bottom of the history, if
	 * any. */
#ifndef DISABLE_TABCOMP
    int last_kbinput = ERR;
	/* The key we pressed before the current key. */
    size_t complete_len = 0;
	/* The length of the original string that we're trying to
	 * tab complete, if any. */
#endif
#endif /* !NANO_TINY */

    answer = mallocstrcpy(answer, curranswer);
    curranswer_len = strlen(answer);

    /* If reset_statusbar_x is TRUE, restore statusbar_x and
     * statusbar_pww to what they were before this prompt.  Then, if
     * statusbar_x is uninitialized or past the end of curranswer, put
     * statusbar_x at the end of the string and update statusbar_pww
     * based on it.  We do these things so that the cursor position
     * stays at the right place if a prompt-changing toggle is pressed,
     * or if this prompt was started from another prompt and we cancel
     * out of it. */
    if (reset_statusbar_x) {
	statusbar_x = old_statusbar_x;
	statusbar_pww = old_pww;
    }

    if (statusbar_x == (size_t)-1 || statusbar_x > curranswer_len) {
	statusbar_x = curranswer_len;
	statusbar_pww = statusbar_xplustabs();
    }

    currmenu = menu;

#ifdef DEBUG
fprintf(stderr, "get_prompt_string: answer = \"%s\", statusbar_x = %lu\n", answer, (unsigned long) statusbar_x);
#endif

    update_statusbar_line(answer, statusbar_x);

    /* Refresh the edit window and the statusbar before getting
     * input. */
    wnoutrefresh(edit);
    wnoutrefresh(bottomwin);

    /* If we're using restricted mode, we aren't allowed to change the
     * name of the current file once it has one, because that would
     * allow writing to files not specified on the command line.  In
     * this case, disable all keys that would change the text if the
     * filename isn't blank and we're at the "Write File" prompt. */
    while (1) {
	kbinput = do_statusbar_input(meta_key, func_key, &have_shortcut,
	    &ran_func, &finished, TRUE, refresh_func);
	assert(statusbar_x <= strlen(answer));

	s = get_shortcut(currmenu, &kbinput, meta_key, func_key);

	if (s)
	    if (s->scfunc == do_cancel || s->scfunc == do_enter_void)
		break;

#ifndef DISABLE_TABCOMP
	if (s && s->scfunc != do_tab)
	    tabbed = FALSE;
#endif

#ifndef DISABLE_TABCOMP
#ifndef NANO_TINY
	if (s && s->scfunc == do_tab) {
		if (history_list != NULL) {
		    if (last_kbinput != sc_seq_or(do_tab, NANO_CONTROL_I))
			complete_len = strlen(answer);

		    if (complete_len > 0) {
			answer = mallocstrcpy(answer,
				get_history_completion(history_list,
				answer, complete_len));
			statusbar_x = strlen(answer);
		    }
		} else
#endif /* !NANO_TINY */
		if (allow_tabs)
		    answer = input_tab(answer, allow_files,
			&statusbar_x, &tabbed, refresh_func, list);

		update_statusbar_line(answer, statusbar_x);
	} else
#endif /* !DISABLE_TABCOMP */
#ifndef NANO_TINY
	if (s && s->scfunc == get_history_older_void) {
		if (history_list != NULL) {
		    /* If we're scrolling up at the bottom of the
		     * history list and answer isn't blank, save answer
		     * in magichistory. */
		    if ((*history_list)->next == NULL &&
			answer[0] != '\0')
			magichistory = mallocstrcpy(magichistory,
				answer);

		    /* Get the older search from the history list and
		     * save it in answer.  If there is no older search,
		     * don't do anything. */
		    if ((history =
			get_history_older(history_list)) != NULL) {
			answer = mallocstrcpy(answer, history);
			statusbar_x = strlen(answer);
		    }

		    update_statusbar_line(answer, statusbar_x);

		    /* This key has a shortcut list entry when it's used
		     * to move to an older search, which means that
		     * finished has been set to TRUE.  Set it back to
		     * FALSE here, so that we aren't kicked out of the
		     * statusbar prompt. */
		    finished = FALSE;
		}
	} else if (s && s->scfunc == get_history_newer_void) {
		if (history_list != NULL) {
		    /* Get the newer search from the history list and
		     * save it in answer.  If there is no newer search,
		     * don't do anything. */
		    if ((history =
			get_history_newer(history_list)) != NULL) {
			answer = mallocstrcpy(answer, history);
			statusbar_x = strlen(answer);
		    }

		    /* If, after scrolling down, we're at the bottom of
		     * the history list, answer is blank, and
		     * magichistory is set, save magichistory in
		     * answer. */
		    if ((*history_list)->next == NULL &&
			*answer == '\0' && magichistory != NULL) {
			answer = mallocstrcpy(answer, magichistory);
			statusbar_x = strlen(answer);
		    }

		    update_statusbar_line(answer, statusbar_x);

		    /* This key has a shortcut list entry when it's used
		     * to move to a newer search, which means that
		     * finished has been set to TRUE.  Set it back to
		     * FALSE here, so that we aren't kicked out of the
		     * statusbar prompt. */
		    finished = FALSE;
		}
	} else
#endif /* !NANO_TINY */
	if (s && s->scfunc == do_help_void) {
		update_statusbar_line(answer, statusbar_x);

		/* This key has a shortcut list entry when it's used to
		 * go to the help browser or display a message
		 * indicating that help is disabled, which means that
		 * finished has been set to TRUE.  Set it back to FALSE
		 * here, so that we aren't kicked out of the statusbar
		 * prompt. */
		finished = FALSE;
	}

	/* If we have a shortcut with an associated function, break out
	 * if we're finished after running or trying to run the
	 * function. */
	if (finished)
	    break;

#if !defined(NANO_TINY) && !defined(DISABLE_TABCOMP)
	last_kbinput = kbinput;
#endif

	reset_statusbar_cursor();
	wnoutrefresh(bottomwin);
    }


#ifndef NANO_TINY
    /* Set the current position in the history list to the bottom and
     * free magichistory, if we need to. */
    if (history_list != NULL) {
	history_reset(*history_list);

	if (magichistory != NULL)
	    free(magichistory);
    }
#endif


    /* We've finished putting in an answer or run a normal shortcut's
     * associated function, so reset statusbar_x and statusbar_pww.  If
     * we've finished putting in an answer, reset the statusbar cursor
     * position too. */
    if (s) {
	if (s->scfunc ==  do_cancel || s->scfunc == do_enter_void ||
	ran_func) {
	    statusbar_x = old_statusbar_x;
	    statusbar_pww = old_pww;

	    if (!ran_func)
		reset_statusbar_x = TRUE;
    /* Otherwise, we're still putting in an answer or a shortcut with
     * an associated function, so leave the statusbar cursor position
     * alone. */
	} else
	    reset_statusbar_x = FALSE;
    }

    *actual = kbinput;
    return s;
}
Exemple #8
0
/* Ask a simple Yes/No (and optionally All) question, specified in msg,
 * on the statusbar.  Return 1 for Yes, 0 for No, 2 for All (if all is
 * TRUE when passed in), and -1 for Cancel. */
int do_yesno_prompt(bool all, const char *msg)
{
    int ok = -2, width = 16;
    const char *yesstr;		/* String of Yes characters accepted. */
    const char *nostr;		/* Same for No. */
    const char *allstr;		/* And All, surprise! */
    const sc *s;
    int oldmenu = currmenu;

    assert(msg != NULL);

    /* yesstr, nostr, and allstr are strings of any length.  Each string
     * consists of all single-byte characters accepted as valid
     * characters for that value.  The first value will be the one
     * displayed in the shortcuts. */
    /* TRANSLATORS: For the next three strings, if possible, specify
     * the single-byte shortcuts for both your language and English.
     * For example, in French: "OoYy" for "Oui". */
    yesstr = _("Yy");
    nostr = _("Nn");
    allstr = _("Aa");

    if (!ISSET(NO_HELP)) {
	char shortstr[3];
		/* Temp string for Yes, No, All. */

	if (COLS < 32)
	    width = COLS / 2;

	/* Clear the shortcut list from the bottom of the screen. */
	blank_bottombars();

	sprintf(shortstr, " %c", yesstr[0]);
	wmove(bottomwin, 1, 0);
	onekey(shortstr, _("Yes"), width);

	if (all) {
	    wmove(bottomwin, 1, width);
	    shortstr[1] = allstr[0];
	    onekey(shortstr, _("All"), width);
	}

	wmove(bottomwin, 2, 0);
	shortstr[1] = nostr[0];
	onekey(shortstr, _("No"), width);

	wmove(bottomwin, 2, 16);
	onekey("^C", _("Cancel"), width);
    }

    wattron(bottomwin, reverse_attr);

    blank_statusbar();
    mvwaddnstr(bottomwin, 0, 0, msg, actual_x(msg, COLS - 1));

     wattroff(bottomwin, reverse_attr);

    /* Refresh the edit window and the statusbar before getting
     * input. */
    wnoutrefresh(edit);
    wnoutrefresh(bottomwin);

    do {
	int kbinput;
	bool meta_key, func_key;
#ifndef DISABLE_MOUSE
	int mouse_x, mouse_y;
#endif

	currmenu = MYESNO;
	kbinput = get_kbinput(bottomwin, &meta_key, &func_key);
	s = get_shortcut(currmenu, &kbinput, &meta_key, &func_key);

	if (s && s->scfunc ==  do_cancel)
	    ok = -1;
#ifndef DISABLE_MOUSE
	else if (kbinput == KEY_MOUSE) {
		/* We can click on the Yes/No/All shortcut list to
		 * select an answer. */
		if (get_mouseinput(&mouse_x, &mouse_y, FALSE) == 0 &&
			wmouse_trafo(bottomwin, &mouse_y, &mouse_x,
			FALSE) && mouse_x < (width * 2) &&
			mouse_y > 0) {
		    int x = mouse_x / width;
			/* Calculate the x-coordinate relative to the
			 * two columns of the Yes/No/All shortcuts in
			 * bottomwin. */
		    int y = mouse_y - 1;
			/* Calculate the y-coordinate relative to the
			 * beginning of the Yes/No/All shortcuts in
			 * bottomwin, i.e. with the sizes of topwin,
			 * edit, and the first line of bottomwin
			 * subtracted out. */

		    assert(0 <= x && x <= 1 && 0 <= y && y <= 1);

		    /* x == 0 means they clicked Yes or No.  y == 0
		     * means Yes or All. */
		    ok = -2 * x * y + x - y + 1;

		    if (ok == 2 && !all)
			ok = -2;
		}
	}
#endif /* !DISABLE_MOUSE */
	else if  (s && s->scfunc == total_refresh) {
	    total_redraw();
	    continue;
	} else {
		/* Look for the kbinput in the Yes, No and (optionally)
		 * All strings. */
		if (strchr(yesstr, kbinput) != NULL)
		    ok = 1;
		else if (strchr(nostr, kbinput) != NULL)
		    ok = 0;
		else if (all && strchr(allstr, kbinput) != NULL)
		    ok = 2;
	}
    } while (ok == -2);

    currmenu = oldmenu;
    return ok;
}
int do_shortcut_menu(void *ignored)
{
    (void)ignored;
    struct simplelist_info list;
    struct shortcut *sc;
    int done = GO_TO_PREVIOUS;
    if (first_handle == 0)
        shortcuts_init();
    simplelist_info_init(&list, P2STR(ID2P(LANG_SHORTCUTS)), shortcut_count, NULL);
    list.get_name = shortcut_menu_get_name;
    list.action_callback = shortcut_menu_get_action;
    if (global_settings.show_icons)
        list.get_icon = shortcut_menu_get_icon;
    list.title_icon = Icon_Bookmark;
    if (global_settings.talk_menu)
        list.get_talk = shortcut_menu_speak_item;

    push_current_activity(ACTIVITY_SHORTCUTSMENU);

    while (done == GO_TO_PREVIOUS)
    {
        if (simplelist_show_list(&list))
            break; /* some error happened?! */
        if (list.selection == -1)
            break;
        else
        {
            sc = get_shortcut(list.selection);
            if (!sc)
                continue;
            switch (sc->type)
            {
                case SHORTCUT_PLAYLISTMENU:
                    if (!file_exists(sc->u.path))
                    {
                        splash(HZ, ID2P(LANG_NO_FILES));
                        break;
                    }
                    else
                    {
                        onplay_show_playlist_menu(sc->u.path);
                    }
                    break;
                case SHORTCUT_FILE:
                    if (!file_exists(sc->u.path))
                    {
                        splash(HZ, ID2P(LANG_NO_FILES));
                        break;
                    }
                    /* else fall through */
                case SHORTCUT_BROWSER:
                {
                    struct browse_context browse;
                    browse_context_init(&browse, global_settings.dirfilter, 0,
                            NULL, NOICON, sc->u.path, NULL);
                    if (sc->type == SHORTCUT_FILE)
                        browse.flags |= BROWSE_RUNFILE;
                    done = rockbox_browse(&browse);
                }
                break;
                case SHORTCUT_SETTING:
                    do_setting_screen(sc->u.setting,
                            sc->name[0] ? sc->name : P2STR(ID2P(sc->u.setting->lang_id)),NULL);
                    break;
                case SHORTCUT_DEBUGITEM:
                    run_debug_screen(sc->u.path);
                    break;
                case SHORTCUT_SHUTDOWN:
#if CONFIG_CHARGING
                    if (charger_inserted())
                        charging_splash();
                    else
#endif
                        sys_poweroff();
                    break;
                case SHORTCUT_TIME:
#if CONFIG_RTC
                  if (sc->u.timedata.talktime) {
                        talk_timedate();
                        talk_force_enqueue_next();
                  } else
#endif
                    {
                        char timer_buf[10];
                        set_sleep_timer(sc->u.timedata.sleep_timeout * 60);
                        splashf(HZ, "%s (%s)", str(LANG_SLEEP_TIMER), 
                                sleep_timer_formatter(timer_buf, sizeof(timer_buf),
                                                      sc->u.timedata.sleep_timeout, NULL));
                    }
                    break;
                case SHORTCUT_UNDEFINED:
                default:
                    break;
            }
        }
    }
    pop_current_activity();
    return done;
}
static int readline_cb(int n, char *buf, void *parameters)
{
    (void)n;
    (void)parameters;
    struct shortcut **param = (struct shortcut**)parameters;
    struct shortcut* sc = *param;
    char *name, *value;

    if (!strcasecmp(skip_whitespace(buf), "[shortcut]"))
    {
        if (sc && verify_shortcut(sc))
            shortcut_count++;
        sc = get_shortcut(shortcut_count);
        if (!sc)
            return 1;
        init_shortcut(sc);
        *param = sc;
    }
    else if (sc && settings_parseline(buf, &name, &value))
    {
        if (!strcmp(name, "type"))
        {
            int t = 0;
            for (t=0; t<SHORTCUT_TYPE_COUNT && sc->type == SHORTCUT_UNDEFINED; t++)
                if (!strcmp(value, type_strings[t]))
                    sc->type = t;
        }
        else if (!strcmp(name, "name"))
        {
            strlcpy(sc->name, value, MAX_SHORTCUT_NAME);
        }
        else if (!strcmp(name, "data"))
        {
            switch (sc->type)
            {
                case SHORTCUT_UNDEFINED:
                case SHORTCUT_TYPE_COUNT:
                    *param = NULL;
                    break;
                case SHORTCUT_BROWSER:
                case SHORTCUT_FILE:
                case SHORTCUT_DEBUGITEM:
                case SHORTCUT_PLAYLISTMENU:
                    strlcpy(sc->u.path, value, MAX_PATH);
                    break;
                case SHORTCUT_SETTING:
                    sc->u.setting = find_setting_by_cfgname(value, NULL);
                    break;
                case SHORTCUT_TIME:
#if CONFIG_RTC
                    sc->u.timedata.talktime = false;
                    if (!strcasecmp(value, "talk"))
                        sc->u.timedata.talktime = true;
                    else
#endif
                    if (!strncasecmp(value, "sleep ", strlen("sleep ")))
                        sc->u.timedata.sleep_timeout = atoi(&value[strlen("sleep ")]);
                    else
                        sc->type = SHORTCUT_UNDEFINED; /* error */
                    break;
                case SHORTCUT_SEPARATOR:
                case SHORTCUT_SHUTDOWN:
                    break;
            }
        }
        else if (!strcmp(name, "icon"))
        {
            if (!strcmp(value, "filetype") && sc->type != SHORTCUT_SETTING && sc->u.path[0])
            {
                sc->icon = filetype_get_icon(filetype_get_attr(sc->u.path));
            }
            else
            {
                sc->icon = atoi(value);
            }
        }
        else if (!strcmp(name, "talkclip"))
        {
            strlcpy(sc->talk_clip, value, MAX_PATH);
        }
    }
    return 0;
}