mirror of
https://github.com/libretro/RetroArch.git
synced 2024-11-27 10:10:57 +00:00
Move code out of retroarch.c and into menu/menu_driver.c
This commit is contained in:
parent
e2e236f1bf
commit
ec55f8188a
@ -20,18 +20,26 @@
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <locale.h>
|
||||
|
||||
#include <retro_timers.h>
|
||||
#include <lists/dir_list.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <compat/strcasestr.h>
|
||||
#include <encodings/utf.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <time/rtime.h>
|
||||
|
||||
#include "menu_driver.h"
|
||||
#include "menu_cbs.h"
|
||||
#include "../list_special.h"
|
||||
#include "../paths.h"
|
||||
#include "../tasks/task_powerstate.h"
|
||||
#include "../tasks/tasks_internal.h"
|
||||
#include "../verbosity.h"
|
||||
|
||||
#include "frontend/frontend_driver.h"
|
||||
|
||||
#ifdef HAVE_LANGEXTRA
|
||||
/* This file has a UTF8 BOM, we assume HAVE_LANGEXTRA
|
||||
* is only enabled for compilers that can support this. */
|
||||
@ -70,6 +78,773 @@ static bool menu_should_pop_stack(const char *label)
|
||||
return false;
|
||||
}
|
||||
|
||||
size_t menu_navigation_get_selection(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
return menu_st->selection_ptr;
|
||||
}
|
||||
|
||||
void menu_navigation_set_selection(size_t val)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_st->selection_ptr = val;
|
||||
}
|
||||
|
||||
void menu_entry_get(menu_entry_t *entry, size_t stack_idx,
|
||||
size_t i, void *userdata, bool use_representation)
|
||||
{
|
||||
char newpath[255];
|
||||
const char *path = NULL;
|
||||
const char *entry_label = NULL;
|
||||
menu_file_list_cbs_t *cbs = NULL;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
file_list_t *selection_buf = MENU_ENTRIES_GET_SELECTION_BUF_PTR_INTERNAL(menu_st, stack_idx);
|
||||
file_list_t *list = (userdata) ? (file_list_t*)userdata : selection_buf;
|
||||
bool path_enabled = entry->path_enabled;
|
||||
|
||||
newpath[0] = '\0';
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
path = list->list[i].path;
|
||||
entry_label = list->list[i].label;
|
||||
entry->type = list->list[i].type;
|
||||
entry->entry_idx = list->list[i].entry_idx;
|
||||
|
||||
cbs = (menu_file_list_cbs_t*)list->list[i].actiondata;
|
||||
entry->idx = (unsigned)i;
|
||||
|
||||
if (entry->label_enabled && !string_is_empty(entry_label))
|
||||
strlcpy(entry->label, entry_label, sizeof(entry->label));
|
||||
|
||||
if (cbs)
|
||||
{
|
||||
const char *label = NULL;
|
||||
|
||||
entry->enum_idx = cbs->enum_idx;
|
||||
entry->checked = cbs->checked;
|
||||
|
||||
file_list_get_last(MENU_LIST_GET(menu_st->entries.list, 0),
|
||||
NULL, &label, NULL, NULL);
|
||||
|
||||
if (entry->rich_label_enabled && cbs->action_label)
|
||||
{
|
||||
cbs->action_label(list,
|
||||
entry->type, (unsigned)i,
|
||||
label, path,
|
||||
entry->rich_label,
|
||||
sizeof(entry->rich_label));
|
||||
|
||||
if (string_is_empty(entry->rich_label))
|
||||
path_enabled = true;
|
||||
}
|
||||
|
||||
if ((path_enabled || entry->value_enabled) &&
|
||||
cbs->action_get_value &&
|
||||
use_representation)
|
||||
{
|
||||
cbs->action_get_value(list,
|
||||
&entry->spacing, entry->type,
|
||||
(unsigned)i, label,
|
||||
entry->value,
|
||||
entry->value_enabled ? sizeof(entry->value) : 0,
|
||||
path,
|
||||
newpath,
|
||||
path_enabled ? sizeof(newpath) : 0);
|
||||
|
||||
if (!string_is_empty(entry->value))
|
||||
{
|
||||
if (entry->enum_idx == MENU_ENUM_LABEL_CHEEVOS_PASSWORD)
|
||||
{
|
||||
size_t j;
|
||||
size_t size = strlcpy(entry->password_value, entry->value,
|
||||
sizeof(entry->password_value));
|
||||
for (j = 0; j < size; j++)
|
||||
entry->password_value[j] = '*';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entry->sublabel_enabled)
|
||||
{
|
||||
if (!string_is_empty(cbs->action_sublabel_cache))
|
||||
strlcpy(entry->sublabel,
|
||||
cbs->action_sublabel_cache, sizeof(entry->sublabel));
|
||||
else if (cbs->action_sublabel)
|
||||
{
|
||||
/* If this function callback returns true,
|
||||
* we know that the value won't change - so we
|
||||
* can cache it instead. */
|
||||
if (cbs->action_sublabel(list,
|
||||
entry->type, (unsigned)i,
|
||||
label, path,
|
||||
entry->sublabel,
|
||||
sizeof(entry->sublabel)) > 0)
|
||||
strlcpy(cbs->action_sublabel_cache,
|
||||
entry->sublabel,
|
||||
sizeof(cbs->action_sublabel_cache));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (path_enabled)
|
||||
{
|
||||
if (!string_is_empty(path) && !use_representation)
|
||||
strlcpy(entry->path, path, sizeof(entry->path));
|
||||
else if (
|
||||
cbs
|
||||
&& cbs->setting
|
||||
&& cbs->setting->enum_value_idx != MSG_UNKNOWN
|
||||
&& !cbs->setting->dont_use_enum_idx_representation)
|
||||
strlcpy(entry->path,
|
||||
msg_hash_to_str(cbs->setting->enum_value_idx),
|
||||
sizeof(entry->path));
|
||||
else
|
||||
if (!string_is_empty(newpath))
|
||||
strlcpy(entry->path, newpath, sizeof(entry->path));
|
||||
}
|
||||
}
|
||||
|
||||
menu_file_list_cbs_t *menu_entries_get_last_stack_actiondata(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
if (menu_st->entries.list)
|
||||
{
|
||||
const file_list_t *list = MENU_LIST_GET(menu_st->entries.list, 0);
|
||||
return (menu_file_list_cbs_t*)list->list[list->size - 1].actiondata;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
file_list_t *menu_entries_get_menu_stack_ptr(size_t idx)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
if (!menu_list)
|
||||
return NULL;
|
||||
return MENU_LIST_GET(menu_list, (unsigned)idx);
|
||||
}
|
||||
|
||||
file_list_t *menu_entries_get_selection_buf_ptr(size_t idx)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
if (!menu_list)
|
||||
return NULL;
|
||||
return MENU_LIST_GET_SELECTION(menu_list, (unsigned)idx);
|
||||
}
|
||||
|
||||
size_t menu_entries_get_stack_size(size_t idx)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
if (!menu_list)
|
||||
return 0;
|
||||
return MENU_LIST_GET_STACK_SIZE(menu_list, idx);
|
||||
}
|
||||
|
||||
size_t menu_entries_get_size(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
if (!menu_list)
|
||||
return 0;
|
||||
return MENU_LIST_GET_SELECTION(menu_list, 0)->size;
|
||||
}
|
||||
|
||||
menu_search_terms_t *menu_entries_search_get_terms_internal(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
file_list_t *list = MENU_LIST_GET(menu_st->entries.list, 0);
|
||||
menu_file_list_cbs_t *cbs = NULL;
|
||||
|
||||
if (!list ||
|
||||
(list->size < 1))
|
||||
return NULL;
|
||||
|
||||
cbs = (menu_file_list_cbs_t*)list->list[list->size - 1].actiondata;
|
||||
|
||||
if (!cbs)
|
||||
return NULL;
|
||||
|
||||
return &cbs->search;
|
||||
}
|
||||
|
||||
/* Searches current menu list for specified 'needle'
|
||||
* string. If string is found, returns true and sets
|
||||
* 'idx' to the matching list entry index. */
|
||||
bool menu_entries_list_search(const char *needle, size_t *idx)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
file_list_t *list = MENU_LIST_GET_SELECTION(menu_list, (unsigned)0);
|
||||
bool match_found = false;
|
||||
bool char_search = false;
|
||||
char needle_char = 0;
|
||||
size_t i;
|
||||
|
||||
if ( !list
|
||||
|| string_is_empty(needle)
|
||||
|| !idx)
|
||||
return match_found;
|
||||
|
||||
/* Check if we are searching for a single
|
||||
* Latin alphabet character */
|
||||
char_search = ((needle[1] == '\0') && (ISALPHA(needle[0])));
|
||||
if (char_search)
|
||||
needle_char = TOLOWER(needle[0]);
|
||||
|
||||
for (i = 0; i < list->size; i++)
|
||||
{
|
||||
const char *entry_label = NULL;
|
||||
menu_entry_t entry;
|
||||
|
||||
/* Note the we have to get the actual menu
|
||||
* entry here, since we need the exact label
|
||||
* that is currently displayed by the menu
|
||||
* driver */
|
||||
MENU_ENTRY_INIT(entry);
|
||||
entry.value_enabled = false;
|
||||
entry.sublabel_enabled = false;
|
||||
menu_entry_get(&entry, 0, i, NULL, true);
|
||||
|
||||
/* When using the file browser, one or more
|
||||
* 'utility' entries will be added to the top
|
||||
* of the list (e.g. 'Parent Directory'). These
|
||||
* have no bearing on the actual content of the
|
||||
* list, and should be excluded from the search */
|
||||
if ((entry.type == FILE_TYPE_SCAN_DIRECTORY) ||
|
||||
(entry.type == FILE_TYPE_MANUAL_SCAN_DIRECTORY) ||
|
||||
(entry.type == FILE_TYPE_USE_DIRECTORY) ||
|
||||
(entry.type == FILE_TYPE_PARENT_DIRECTORY))
|
||||
continue;
|
||||
|
||||
/* Get displayed entry label */
|
||||
if (!string_is_empty(entry.rich_label))
|
||||
entry_label = entry.rich_label;
|
||||
else
|
||||
entry_label = entry.path;
|
||||
|
||||
if (string_is_empty(entry_label))
|
||||
continue;
|
||||
|
||||
/* If we are performing a single character
|
||||
* search, jump to the first entry whose
|
||||
* first character matches */
|
||||
if (char_search)
|
||||
{
|
||||
if (needle_char == TOLOWER(entry_label[0]))
|
||||
{
|
||||
*idx = i;
|
||||
match_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Otherwise perform an exhaustive string
|
||||
* comparison */
|
||||
else
|
||||
{
|
||||
const char *found_str = (const char *)strcasestr(entry_label, needle);
|
||||
|
||||
/* Found a match with the first characters
|
||||
* of the label -> best possible match,
|
||||
* so quit immediately */
|
||||
if (found_str == entry_label)
|
||||
{
|
||||
*idx = i;
|
||||
match_found = true;
|
||||
break;
|
||||
}
|
||||
/* Found a mid-string match; this is a valid
|
||||
* result, but keep searching for the best
|
||||
* possible match */
|
||||
else if (found_str)
|
||||
{
|
||||
*idx = i;
|
||||
match_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match_found;
|
||||
}
|
||||
|
||||
/* Time format strings with AM-PM designation require special
|
||||
* handling due to platform dependence */
|
||||
static void strftime_am_pm(char* ptr, size_t maxsize, const char* format,
|
||||
const struct tm* timeptr)
|
||||
{
|
||||
char *local = NULL;
|
||||
|
||||
/* Ensure correct locale is set
|
||||
* > Required for localised AM/PM strings */
|
||||
setlocale(LC_TIME, "");
|
||||
|
||||
strftime(ptr, maxsize, format, timeptr);
|
||||
#if !(defined(__linux__) && !defined(ANDROID))
|
||||
local = local_to_utf8_string_alloc(ptr);
|
||||
|
||||
if (!string_is_empty(local))
|
||||
strlcpy(ptr, local, maxsize);
|
||||
|
||||
if (local)
|
||||
{
|
||||
free(local);
|
||||
local = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Display the date and time - time_mode will influence how
|
||||
* the time representation will look like.
|
||||
* */
|
||||
void menu_display_timedate(gfx_display_ctx_datetime_t *datetime)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
if (!datetime)
|
||||
return;
|
||||
|
||||
/* Trigger an update, if required */
|
||||
if (menu_st->current_time_us - menu_st->datetime_last_time_us >=
|
||||
DATETIME_CHECK_INTERVAL)
|
||||
{
|
||||
time_t time_;
|
||||
struct tm tm_;
|
||||
bool has_am_pm = false;
|
||||
const char *format_str = "";
|
||||
|
||||
menu_st->datetime_last_time_us = menu_st->current_time_us;
|
||||
|
||||
/* Get current time */
|
||||
time(&time_);
|
||||
rtime_localtime(&time_, &tm_);
|
||||
|
||||
/* Format string representation */
|
||||
switch (datetime->time_mode)
|
||||
{
|
||||
case MENU_TIMEDATE_STYLE_YMD_HMS: /* YYYY-MM-DD HH:MM:SS */
|
||||
/* Using switch statements to set the format
|
||||
* string is verbose, but has far less performance
|
||||
* impact than setting the date separator dynamically
|
||||
* (i.e. no snprintf() or character replacement...) */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d %H:%M:%S";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d %H:%M:%S";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d %H:%M:%S";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YMD_HM: /* YYYY-MM-DD HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YMD: /* YYYY-MM-DD */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YM: /* YYYY-MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY_HMS: /* MM-DD-YYYY HH:MM:SS */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y %H:%M:%S";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y %H:%M:%S";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y %H:%M:%S";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY_HM: /* MM-DD-YYYY HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MD_HM: /* MM-DD HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY: /* MM-DD-YYYY */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MD: /* MM-DD */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY_HMS: /* DD-MM-YYYY HH:MM:SS */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y %H:%M:%S";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y %H:%M:%S";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y %H:%M:%S";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY_HM: /* DD-MM-YYYY HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMM_HM: /* DD-MM HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY: /* DD-MM-YYYY */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMM: /* DD-MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_HMS: /* HH:MM:SS */
|
||||
format_str = "%H:%M:%S";
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_HM: /* HH:MM */
|
||||
format_str = "%H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YMD_HMS_AMPM: /* YYYY-MM-DD HH:MM:SS (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d %I:%M:%S %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d %I:%M:%S %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d %I:%M:%S %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YMD_HM_AMPM: /* YYYY-MM-DD HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY_HMS_AMPM: /* MM-DD-YYYY HH:MM:SS (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y %I:%M:%S %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y %I:%M:%S %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y %I:%M:%S %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY_HM_AMPM: /* MM-DD-YYYY HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MD_HM_AMPM: /* MM-DD HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY_HMS_AMPM: /* DD-MM-YYYY HH:MM:SS (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y %I:%M:%S %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y %I:%M:%S %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y %I:%M:%S %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY_HM_AMPM: /* DD-MM-YYYY HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMM_HM_AMPM: /* DD-MM HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_HMS_AMPM: /* HH:MM:SS (AM/PM) */
|
||||
has_am_pm = true;
|
||||
format_str = "%I:%M:%S %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_HM_AMPM: /* HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
format_str = "%I:%M %p";
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_am_pm)
|
||||
strftime_am_pm(menu_st->datetime_cache, sizeof(menu_st->datetime_cache),
|
||||
format_str, &tm_);
|
||||
else
|
||||
strftime(menu_st->datetime_cache, sizeof(menu_st->datetime_cache),
|
||||
format_str, &tm_);
|
||||
}
|
||||
|
||||
/* Copy cached datetime string to input
|
||||
* menu_display_ctx_datetime_t struct */
|
||||
strlcpy(datetime->s, menu_st->datetime_cache, datetime->len);
|
||||
}
|
||||
|
||||
/* Display current (battery) power state */
|
||||
void menu_display_powerstate(gfx_display_ctx_powerstate_t *powerstate)
|
||||
{
|
||||
int percent = 0;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
enum frontend_powerstate state = FRONTEND_POWERSTATE_NONE;
|
||||
|
||||
if (!powerstate)
|
||||
return;
|
||||
|
||||
/* Trigger an update, if required */
|
||||
if (menu_st->current_time_us - menu_st->powerstate_last_time_us >=
|
||||
POWERSTATE_CHECK_INTERVAL)
|
||||
{
|
||||
menu_st->powerstate_last_time_us = menu_st->current_time_us;
|
||||
task_push_get_powerstate();
|
||||
}
|
||||
|
||||
/* Get last recorded state */
|
||||
state = get_last_powerstate(&percent);
|
||||
|
||||
/* Populate gfx_display_ctx_powerstate_t */
|
||||
powerstate->battery_enabled = (state != FRONTEND_POWERSTATE_NONE) &&
|
||||
(state != FRONTEND_POWERSTATE_NO_SOURCE);
|
||||
powerstate->percent = 0;
|
||||
powerstate->charging = false;
|
||||
|
||||
if (powerstate->battery_enabled)
|
||||
{
|
||||
if (state == FRONTEND_POWERSTATE_CHARGING)
|
||||
powerstate->charging = true;
|
||||
if (percent > 0)
|
||||
powerstate->percent = (unsigned)percent;
|
||||
snprintf(powerstate->s, powerstate->len, "%u%%", powerstate->percent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Sets title to what the name of the current menu should be. */
|
||||
int menu_entries_get_title(char *s, size_t len)
|
||||
{
|
||||
unsigned menu_type = 0;
|
||||
const char *path = NULL;
|
||||
const char *label = NULL;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
const file_list_t *list = menu_st->entries.list ?
|
||||
MENU_LIST_GET(menu_st->entries.list, 0) : NULL;
|
||||
menu_file_list_cbs_t *cbs = list
|
||||
? (menu_file_list_cbs_t*)list->list[list->size - 1].actiondata
|
||||
: NULL;
|
||||
|
||||
if (!cbs)
|
||||
return -1;
|
||||
|
||||
if (cbs && cbs->action_get_title)
|
||||
{
|
||||
int ret;
|
||||
if (!string_is_empty(cbs->action_title_cache))
|
||||
{
|
||||
strlcpy(s, cbs->action_title_cache, len);
|
||||
return 0;
|
||||
}
|
||||
file_list_get_last(MENU_LIST_GET(menu_st->entries.list, 0),
|
||||
&path, &label, &menu_type, NULL);
|
||||
ret = cbs->action_get_title(path, label, menu_type, s, len);
|
||||
if (ret == 1)
|
||||
strlcpy(cbs->action_title_cache, s, sizeof(cbs->action_title_cache));
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Used to close an active message box (help or info)
|
||||
* TODO/FIXME: The way that message boxes are handled
|
||||
* is complete garbage. generic_menu_iterate() and
|
||||
@ -2920,3 +3695,130 @@ void get_current_menu_sublabel(struct menu_state *menu_st,
|
||||
menu_entry_get(&entry, 0, menu_st->selection_ptr, NULL, true);
|
||||
strlcpy(s, entry.sublabel, len);
|
||||
}
|
||||
|
||||
void menu_entries_get_last_stack(const char **path, const char **label,
|
||||
unsigned *file_type, enum msg_hash_enums *enum_idx, size_t *entry_idx)
|
||||
{
|
||||
file_list_t *list = NULL;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
if (!menu_st->entries.list)
|
||||
return;
|
||||
|
||||
list = MENU_LIST_GET(menu_st->entries.list, 0);
|
||||
|
||||
if (list && list->size)
|
||||
file_list_get_at_offset(list, list->size - 1, path, label, file_type, entry_idx);
|
||||
|
||||
if (enum_idx)
|
||||
{
|
||||
menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)
|
||||
list->list[list->size - 1].actiondata;
|
||||
|
||||
if (cbs)
|
||||
*enum_idx = cbs->enum_idx;
|
||||
}
|
||||
}
|
||||
|
||||
int menu_driver_deferred_push_content_list(file_list_t *list)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, (unsigned)0);
|
||||
|
||||
menu_st->selection_ptr = 0;
|
||||
|
||||
if (!menu_driver_displaylist_push(
|
||||
menu_st,
|
||||
settings,
|
||||
list,
|
||||
selection_buf))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool menu_driver_screensaver_supported(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
return menu_st->screensaver_supported;
|
||||
}
|
||||
|
||||
retro_time_t menu_driver_get_current_time(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
return menu_st->current_time_us;
|
||||
}
|
||||
|
||||
const char *menu_driver_get_pending_selection(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
return menu_st->pending_selection;
|
||||
}
|
||||
|
||||
void menu_driver_set_pending_selection(const char *pending_selection)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
char *selection = menu_st->pending_selection;
|
||||
|
||||
/* Reset existing cache */
|
||||
selection[0] = '\0';
|
||||
|
||||
/* If path is empty, do nothing */
|
||||
if (string_is_empty(pending_selection))
|
||||
return;
|
||||
|
||||
strlcpy(selection, pending_selection,
|
||||
sizeof(menu_st->pending_selection));
|
||||
}
|
||||
|
||||
void menu_input_search_cb(void *userdata, const char *str)
|
||||
{
|
||||
const char *label = NULL;
|
||||
unsigned type = MENU_SETTINGS_NONE;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
|
||||
if (string_is_empty(str))
|
||||
goto end;
|
||||
|
||||
/* Determine whether we are currently
|
||||
* viewing a menu list with 'search
|
||||
* filter' support */
|
||||
file_list_get_last(MENU_LIST_GET(menu_st->entries.list, 0),
|
||||
NULL, &label, &type, NULL);
|
||||
|
||||
/* Do not apply search filter if string
|
||||
* consists of a single Latin alphabet
|
||||
* character */
|
||||
if (((str[1] != '\0') || (!ISALPHA(str[0]))) &&
|
||||
menu_driver_search_filter_enabled(label, type))
|
||||
{
|
||||
/* Add search term */
|
||||
if (menu_entries_search_push(str))
|
||||
{
|
||||
bool refresh = false;
|
||||
|
||||
/* Reset navigation pointer */
|
||||
menu_st->selection_ptr = 0;
|
||||
menu_driver_navigation_set(false);
|
||||
|
||||
/* Refresh menu */
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
|
||||
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
|
||||
}
|
||||
}
|
||||
/* Perform a regular search: jump to the
|
||||
* first matching entry */
|
||||
else
|
||||
{
|
||||
size_t idx = 0;
|
||||
|
||||
if (menu_entries_list_search(str, &idx))
|
||||
{
|
||||
menu_st->selection_ptr = idx;
|
||||
menu_driver_navigation_set(true);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
menu_input_dialog_end();
|
||||
}
|
||||
|
@ -821,6 +821,8 @@ extern menu_ctx_driver_t menu_ctx_mui;
|
||||
extern menu_ctx_driver_t menu_ctx_xmb;
|
||||
extern menu_ctx_driver_t menu_ctx_stripes;
|
||||
|
||||
void menu_input_search_cb(void *userdata, const char *str);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
892
retroarch.c
892
retroarch.c
@ -348,12 +348,6 @@ struct menu_state *menu_state_get_ptr(void)
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
return &p_rarch->menu_driver_state;
|
||||
}
|
||||
|
||||
size_t menu_navigation_get_selection(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
return menu_st->selection_ptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct retro_hw_render_callback *video_driver_get_hw_context(void)
|
||||
@ -1533,128 +1527,6 @@ int generic_menu_entry_action(
|
||||
return ret;
|
||||
}
|
||||
|
||||
void menu_navigation_set_selection(size_t val)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_st->selection_ptr = val;
|
||||
}
|
||||
|
||||
void menu_entry_get(menu_entry_t *entry, size_t stack_idx,
|
||||
size_t i, void *userdata, bool use_representation)
|
||||
{
|
||||
char newpath[255];
|
||||
const char *path = NULL;
|
||||
const char *entry_label = NULL;
|
||||
menu_file_list_cbs_t *cbs = NULL;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
file_list_t *selection_buf = MENU_ENTRIES_GET_SELECTION_BUF_PTR_INTERNAL(menu_st, stack_idx);
|
||||
file_list_t *list = (userdata) ? (file_list_t*)userdata : selection_buf;
|
||||
bool path_enabled = entry->path_enabled;
|
||||
|
||||
newpath[0] = '\0';
|
||||
|
||||
if (!list)
|
||||
return;
|
||||
|
||||
path = list->list[i].path;
|
||||
entry_label = list->list[i].label;
|
||||
entry->type = list->list[i].type;
|
||||
entry->entry_idx = list->list[i].entry_idx;
|
||||
|
||||
cbs = (menu_file_list_cbs_t*)list->list[i].actiondata;
|
||||
entry->idx = (unsigned)i;
|
||||
|
||||
if (entry->label_enabled && !string_is_empty(entry_label))
|
||||
strlcpy(entry->label, entry_label, sizeof(entry->label));
|
||||
|
||||
if (cbs)
|
||||
{
|
||||
const char *label = NULL;
|
||||
|
||||
entry->enum_idx = cbs->enum_idx;
|
||||
entry->checked = cbs->checked;
|
||||
|
||||
file_list_get_last(MENU_LIST_GET(menu_st->entries.list, 0),
|
||||
NULL, &label, NULL, NULL);
|
||||
|
||||
if (entry->rich_label_enabled && cbs->action_label)
|
||||
{
|
||||
cbs->action_label(list,
|
||||
entry->type, (unsigned)i,
|
||||
label, path,
|
||||
entry->rich_label,
|
||||
sizeof(entry->rich_label));
|
||||
|
||||
if (string_is_empty(entry->rich_label))
|
||||
path_enabled = true;
|
||||
}
|
||||
|
||||
if ((path_enabled || entry->value_enabled) &&
|
||||
cbs->action_get_value &&
|
||||
use_representation)
|
||||
{
|
||||
cbs->action_get_value(list,
|
||||
&entry->spacing, entry->type,
|
||||
(unsigned)i, label,
|
||||
entry->value,
|
||||
entry->value_enabled ? sizeof(entry->value) : 0,
|
||||
path,
|
||||
newpath,
|
||||
path_enabled ? sizeof(newpath) : 0);
|
||||
|
||||
if (!string_is_empty(entry->value))
|
||||
{
|
||||
if (entry->enum_idx == MENU_ENUM_LABEL_CHEEVOS_PASSWORD)
|
||||
{
|
||||
size_t j;
|
||||
size_t size = strlcpy(entry->password_value, entry->value,
|
||||
sizeof(entry->password_value));
|
||||
for (j = 0; j < size; j++)
|
||||
entry->password_value[j] = '*';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (entry->sublabel_enabled)
|
||||
{
|
||||
if (!string_is_empty(cbs->action_sublabel_cache))
|
||||
strlcpy(entry->sublabel,
|
||||
cbs->action_sublabel_cache, sizeof(entry->sublabel));
|
||||
else if (cbs->action_sublabel)
|
||||
{
|
||||
/* If this function callback returns true,
|
||||
* we know that the value won't change - so we
|
||||
* can cache it instead. */
|
||||
if (cbs->action_sublabel(list,
|
||||
entry->type, (unsigned)i,
|
||||
label, path,
|
||||
entry->sublabel,
|
||||
sizeof(entry->sublabel)) > 0)
|
||||
strlcpy(cbs->action_sublabel_cache,
|
||||
entry->sublabel,
|
||||
sizeof(cbs->action_sublabel_cache));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (path_enabled)
|
||||
{
|
||||
if (!string_is_empty(path) && !use_representation)
|
||||
strlcpy(entry->path, path, sizeof(entry->path));
|
||||
else if (
|
||||
cbs
|
||||
&& cbs->setting
|
||||
&& cbs->setting->enum_value_idx != MSG_UNKNOWN
|
||||
&& !cbs->setting->dont_use_enum_idx_representation)
|
||||
strlcpy(entry->path,
|
||||
msg_hash_to_str(cbs->setting->enum_value_idx),
|
||||
sizeof(entry->path));
|
||||
else
|
||||
if (!string_is_empty(newpath))
|
||||
strlcpy(entry->path, newpath, sizeof(entry->path));
|
||||
}
|
||||
}
|
||||
|
||||
int menu_entry_action(
|
||||
menu_entry_t *entry, size_t i, enum menu_action action)
|
||||
{
|
||||
@ -1666,51 +1538,6 @@ int menu_entry_action(
|
||||
return -1;
|
||||
}
|
||||
|
||||
menu_file_list_cbs_t *menu_entries_get_last_stack_actiondata(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
if (menu_st->entries.list)
|
||||
{
|
||||
const file_list_t *list = MENU_LIST_GET(menu_st->entries.list, 0);
|
||||
return (menu_file_list_cbs_t*)list->list[list->size - 1].actiondata;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Sets title to what the name of the current menu should be. */
|
||||
int menu_entries_get_title(char *s, size_t len)
|
||||
{
|
||||
unsigned menu_type = 0;
|
||||
const char *path = NULL;
|
||||
const char *label = NULL;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
const file_list_t *list = menu_st->entries.list ?
|
||||
MENU_LIST_GET(menu_st->entries.list, 0) : NULL;
|
||||
menu_file_list_cbs_t *cbs = list
|
||||
? (menu_file_list_cbs_t*)list->list[list->size - 1].actiondata
|
||||
: NULL;
|
||||
|
||||
if (!cbs)
|
||||
return -1;
|
||||
|
||||
if (cbs && cbs->action_get_title)
|
||||
{
|
||||
int ret;
|
||||
if (!string_is_empty(cbs->action_title_cache))
|
||||
{
|
||||
strlcpy(s, cbs->action_title_cache, len);
|
||||
return 0;
|
||||
}
|
||||
file_list_get_last(MENU_LIST_GET(menu_st->entries.list, 0),
|
||||
&path, &label, &menu_type, NULL);
|
||||
ret = cbs->action_get_title(path, label, menu_type, s, len);
|
||||
if (ret == 1)
|
||||
strlcpy(cbs->action_title_cache, s, sizeof(cbs->action_title_cache));
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if defined(_MSC_VER)
|
||||
static const char * msvc_vercode_to_str(const unsigned vercode)
|
||||
{
|
||||
@ -1775,24 +1602,6 @@ int menu_entries_get_core_title(char *s, size_t len)
|
||||
return 0;
|
||||
}
|
||||
|
||||
file_list_t *menu_entries_get_menu_stack_ptr(size_t idx)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
if (!menu_list)
|
||||
return NULL;
|
||||
return MENU_LIST_GET(menu_list, (unsigned)idx);
|
||||
}
|
||||
|
||||
file_list_t *menu_entries_get_selection_buf_ptr(size_t idx)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
if (!menu_list)
|
||||
return NULL;
|
||||
return MENU_LIST_GET_SELECTION(menu_list, (unsigned)idx);
|
||||
}
|
||||
|
||||
void menu_entries_append(
|
||||
file_list_t *list,
|
||||
const char *path,
|
||||
@ -2057,29 +1866,6 @@ void menu_entries_prepend(file_list_t *list,
|
||||
list, cbs, path, label, type, idx);
|
||||
}
|
||||
|
||||
void menu_entries_get_last_stack(const char **path, const char **label,
|
||||
unsigned *file_type, enum msg_hash_enums *enum_idx, size_t *entry_idx)
|
||||
{
|
||||
file_list_t *list = NULL;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
if (!menu_st->entries.list)
|
||||
return;
|
||||
|
||||
list = MENU_LIST_GET(menu_st->entries.list, 0);
|
||||
|
||||
if (list && list->size)
|
||||
file_list_get_at_offset(list, list->size - 1, path, label, file_type, entry_idx);
|
||||
|
||||
if (enum_idx)
|
||||
{
|
||||
menu_file_list_cbs_t *cbs = (menu_file_list_cbs_t*)
|
||||
list->list[list->size - 1].actiondata;
|
||||
|
||||
if (cbs)
|
||||
*enum_idx = cbs->enum_idx;
|
||||
}
|
||||
}
|
||||
|
||||
void menu_entries_flush_stack(const char *needle, unsigned final_type)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
@ -2119,24 +1905,6 @@ void menu_entries_pop_stack(size_t *ptr, size_t idx, bool animate)
|
||||
}
|
||||
}
|
||||
|
||||
size_t menu_entries_get_stack_size(size_t idx)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
if (!menu_list)
|
||||
return 0;
|
||||
return MENU_LIST_GET_STACK_SIZE(menu_list, idx);
|
||||
}
|
||||
|
||||
size_t menu_entries_get_size(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
if (!menu_list)
|
||||
return 0;
|
||||
return MENU_LIST_GET_SELECTION(menu_list, 0)->size;
|
||||
}
|
||||
|
||||
bool menu_entries_ctl(enum menu_entries_ctl_state state, void *data)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
@ -2261,123 +2029,6 @@ bool menu_entries_ctl(enum menu_entries_ctl_state state, void *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
menu_search_terms_t *menu_entries_search_get_terms_internal(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
file_list_t *list = MENU_LIST_GET(menu_st->entries.list, 0);
|
||||
menu_file_list_cbs_t *cbs = NULL;
|
||||
|
||||
if (!list ||
|
||||
(list->size < 1))
|
||||
return NULL;
|
||||
|
||||
cbs = (menu_file_list_cbs_t*)list->list[list->size - 1].actiondata;
|
||||
|
||||
if (!cbs)
|
||||
return NULL;
|
||||
|
||||
return &cbs->search;
|
||||
}
|
||||
|
||||
/* Searches current menu list for specified 'needle'
|
||||
* string. If string is found, returns true and sets
|
||||
* 'idx' to the matching list entry index. */
|
||||
bool menu_entries_list_search(const char *needle, size_t *idx)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
file_list_t *list = MENU_LIST_GET_SELECTION(menu_list, (unsigned)0);
|
||||
bool match_found = false;
|
||||
bool char_search = false;
|
||||
char needle_char = 0;
|
||||
size_t i;
|
||||
|
||||
if ( !list
|
||||
|| string_is_empty(needle)
|
||||
|| !idx)
|
||||
return match_found;
|
||||
|
||||
/* Check if we are searching for a single
|
||||
* Latin alphabet character */
|
||||
char_search = ((needle[1] == '\0') && (ISALPHA(needle[0])));
|
||||
if (char_search)
|
||||
needle_char = TOLOWER(needle[0]);
|
||||
|
||||
for (i = 0; i < list->size; i++)
|
||||
{
|
||||
const char *entry_label = NULL;
|
||||
menu_entry_t entry;
|
||||
|
||||
/* Note the we have to get the actual menu
|
||||
* entry here, since we need the exact label
|
||||
* that is currently displayed by the menu
|
||||
* driver */
|
||||
MENU_ENTRY_INIT(entry);
|
||||
entry.value_enabled = false;
|
||||
entry.sublabel_enabled = false;
|
||||
menu_entry_get(&entry, 0, i, NULL, true);
|
||||
|
||||
/* When using the file browser, one or more
|
||||
* 'utility' entries will be added to the top
|
||||
* of the list (e.g. 'Parent Directory'). These
|
||||
* have no bearing on the actual content of the
|
||||
* list, and should be excluded from the search */
|
||||
if ((entry.type == FILE_TYPE_SCAN_DIRECTORY) ||
|
||||
(entry.type == FILE_TYPE_MANUAL_SCAN_DIRECTORY) ||
|
||||
(entry.type == FILE_TYPE_USE_DIRECTORY) ||
|
||||
(entry.type == FILE_TYPE_PARENT_DIRECTORY))
|
||||
continue;
|
||||
|
||||
/* Get displayed entry label */
|
||||
if (!string_is_empty(entry.rich_label))
|
||||
entry_label = entry.rich_label;
|
||||
else
|
||||
entry_label = entry.path;
|
||||
|
||||
if (string_is_empty(entry_label))
|
||||
continue;
|
||||
|
||||
/* If we are performing a single character
|
||||
* search, jump to the first entry whose
|
||||
* first character matches */
|
||||
if (char_search)
|
||||
{
|
||||
if (needle_char == TOLOWER(entry_label[0]))
|
||||
{
|
||||
*idx = i;
|
||||
match_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
/* Otherwise perform an exhaustive string
|
||||
* comparison */
|
||||
else
|
||||
{
|
||||
const char *found_str = (const char *)strcasestr(entry_label, needle);
|
||||
|
||||
/* Found a match with the first characters
|
||||
* of the label -> best possible match,
|
||||
* so quit immediately */
|
||||
if (found_str == entry_label)
|
||||
{
|
||||
*idx = i;
|
||||
match_found = true;
|
||||
break;
|
||||
}
|
||||
/* Found a mid-string match; this is a valid
|
||||
* result, but keep searching for the best
|
||||
* possible match */
|
||||
else if (found_str)
|
||||
{
|
||||
*idx = i;
|
||||
match_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return match_found;
|
||||
}
|
||||
|
||||
/* TODO/FIXME - seems only RGUI uses this - can this be
|
||||
* refactored away or we can have one common function used
|
||||
* across all menu drivers? */
|
||||
@ -2494,445 +2145,6 @@ void menu_driver_frame(bool menu_is_alive, video_frame_info_t *video_info)
|
||||
p_rarch->menu_driver_ctx->frame(p_rarch->menu_userdata, video_info);
|
||||
}
|
||||
|
||||
/* Time format strings with AM-PM designation require special
|
||||
* handling due to platform dependence */
|
||||
static void strftime_am_pm(char* ptr, size_t maxsize, const char* format,
|
||||
const struct tm* timeptr)
|
||||
{
|
||||
char *local = NULL;
|
||||
|
||||
/* Ensure correct locale is set
|
||||
* > Required for localised AM/PM strings */
|
||||
setlocale(LC_TIME, "");
|
||||
|
||||
strftime(ptr, maxsize, format, timeptr);
|
||||
#if !(defined(__linux__) && !defined(ANDROID))
|
||||
local = local_to_utf8_string_alloc(ptr);
|
||||
|
||||
if (!string_is_empty(local))
|
||||
strlcpy(ptr, local, maxsize);
|
||||
|
||||
if (local)
|
||||
{
|
||||
free(local);
|
||||
local = NULL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Display the date and time - time_mode will influence how
|
||||
* the time representation will look like.
|
||||
* */
|
||||
void menu_display_timedate(gfx_display_ctx_datetime_t *datetime)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
if (!datetime)
|
||||
return;
|
||||
|
||||
/* Trigger an update, if required */
|
||||
if (menu_st->current_time_us - menu_st->datetime_last_time_us >=
|
||||
DATETIME_CHECK_INTERVAL)
|
||||
{
|
||||
time_t time_;
|
||||
struct tm tm_;
|
||||
bool has_am_pm = false;
|
||||
const char *format_str = "";
|
||||
|
||||
menu_st->datetime_last_time_us = menu_st->current_time_us;
|
||||
|
||||
/* Get current time */
|
||||
time(&time_);
|
||||
rtime_localtime(&time_, &tm_);
|
||||
|
||||
/* Format string representation */
|
||||
switch (datetime->time_mode)
|
||||
{
|
||||
case MENU_TIMEDATE_STYLE_YMD_HMS: /* YYYY-MM-DD HH:MM:SS */
|
||||
/* Using switch statements to set the format
|
||||
* string is verbose, but has far less performance
|
||||
* impact than setting the date separator dynamically
|
||||
* (i.e. no snprintf() or character replacement...) */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d %H:%M:%S";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d %H:%M:%S";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d %H:%M:%S";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YMD_HM: /* YYYY-MM-DD HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YMD: /* YYYY-MM-DD */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YM: /* YYYY-MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY_HMS: /* MM-DD-YYYY HH:MM:SS */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y %H:%M:%S";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y %H:%M:%S";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y %H:%M:%S";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY_HM: /* MM-DD-YYYY HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MD_HM: /* MM-DD HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY: /* MM-DD-YYYY */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MD: /* MM-DD */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY_HMS: /* DD-MM-YYYY HH:MM:SS */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y %H:%M:%S";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y %H:%M:%S";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y %H:%M:%S";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY_HM: /* DD-MM-YYYY HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMM_HM: /* DD-MM HH:MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m %H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m %H:%M";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m %H:%M";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY: /* DD-MM-YYYY */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMM: /* DD-MM */
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_HMS: /* HH:MM:SS */
|
||||
format_str = "%H:%M:%S";
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_HM: /* HH:MM */
|
||||
format_str = "%H:%M";
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YMD_HMS_AMPM: /* YYYY-MM-DD HH:MM:SS (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d %I:%M:%S %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d %I:%M:%S %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d %I:%M:%S %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_YMD_HM_AMPM: /* YYYY-MM-DD HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%Y/%m/%d %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%Y.%m.%d %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%Y-%m-%d %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY_HMS_AMPM: /* MM-DD-YYYY HH:MM:SS (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y %I:%M:%S %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y %I:%M:%S %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y %I:%M:%S %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MDYYYY_HM_AMPM: /* MM-DD-YYYY HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d/%Y %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d.%Y %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d-%Y %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_MD_HM_AMPM: /* MM-DD HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%m/%d %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%m.%d %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%m-%d %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY_HMS_AMPM: /* DD-MM-YYYY HH:MM:SS (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y %I:%M:%S %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y %I:%M:%S %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y %I:%M:%S %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMMYYYY_HM_AMPM: /* DD-MM-YYYY HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m/%Y %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m.%Y %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m-%Y %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_DDMM_HM_AMPM: /* DD-MM HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
switch (datetime->date_separator)
|
||||
{
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_SLASH:
|
||||
format_str = "%d/%m %I:%M %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_DATE_SEPARATOR_PERIOD:
|
||||
format_str = "%d.%m %I:%M %p";
|
||||
break;
|
||||
default:
|
||||
format_str = "%d-%m %I:%M %p";
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_HMS_AMPM: /* HH:MM:SS (AM/PM) */
|
||||
has_am_pm = true;
|
||||
format_str = "%I:%M:%S %p";
|
||||
break;
|
||||
case MENU_TIMEDATE_STYLE_HM_AMPM: /* HH:MM (AM/PM) */
|
||||
has_am_pm = true;
|
||||
format_str = "%I:%M %p";
|
||||
break;
|
||||
}
|
||||
|
||||
if (has_am_pm)
|
||||
strftime_am_pm(menu_st->datetime_cache, sizeof(menu_st->datetime_cache),
|
||||
format_str, &tm_);
|
||||
else
|
||||
strftime(menu_st->datetime_cache, sizeof(menu_st->datetime_cache),
|
||||
format_str, &tm_);
|
||||
}
|
||||
|
||||
/* Copy cached datetime string to input
|
||||
* menu_display_ctx_datetime_t struct */
|
||||
strlcpy(datetime->s, menu_st->datetime_cache, datetime->len);
|
||||
}
|
||||
|
||||
/* Display current (battery) power state */
|
||||
void menu_display_powerstate(gfx_display_ctx_powerstate_t *powerstate)
|
||||
{
|
||||
int percent = 0;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
enum frontend_powerstate state = FRONTEND_POWERSTATE_NONE;
|
||||
|
||||
if (!powerstate)
|
||||
return;
|
||||
|
||||
/* Trigger an update, if required */
|
||||
if (menu_st->current_time_us - menu_st->powerstate_last_time_us >=
|
||||
POWERSTATE_CHECK_INTERVAL)
|
||||
{
|
||||
menu_st->powerstate_last_time_us = menu_st->current_time_us;
|
||||
task_push_get_powerstate();
|
||||
}
|
||||
|
||||
/* Get last recorded state */
|
||||
state = get_last_powerstate(&percent);
|
||||
|
||||
/* Populate gfx_display_ctx_powerstate_t */
|
||||
powerstate->battery_enabled = (state != FRONTEND_POWERSTATE_NONE) &&
|
||||
(state != FRONTEND_POWERSTATE_NO_SOURCE);
|
||||
powerstate->percent = 0;
|
||||
powerstate->charging = false;
|
||||
|
||||
if (powerstate->battery_enabled)
|
||||
{
|
||||
if (state == FRONTEND_POWERSTATE_CHARGING)
|
||||
powerstate->charging = true;
|
||||
if (percent > 0)
|
||||
powerstate->percent = (unsigned)percent;
|
||||
snprintf(powerstate->s, powerstate->len, "%u%%", powerstate->percent);
|
||||
}
|
||||
}
|
||||
|
||||
/* Iterate the menu driver for one frame. */
|
||||
static bool menu_driver_iterate(
|
||||
struct rarch_state *p_rarch,
|
||||
@ -2955,24 +2167,6 @@ static bool menu_driver_iterate(
|
||||
current_time) != -1);
|
||||
}
|
||||
|
||||
int menu_driver_deferred_push_content_list(file_list_t *list)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
menu_list_t *menu_list = menu_st->entries.list;
|
||||
file_list_t *selection_buf = MENU_LIST_GET_SELECTION(menu_list, (unsigned)0);
|
||||
|
||||
menu_st->selection_ptr = 0;
|
||||
|
||||
if (!menu_driver_displaylist_push(
|
||||
menu_st,
|
||||
settings,
|
||||
list,
|
||||
selection_buf))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool menu_driver_list_cache(menu_ctx_list_t *list)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
@ -3189,18 +2383,6 @@ bool menu_driver_list_get_size(menu_ctx_list_t *list)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool menu_driver_screensaver_supported(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
return menu_st->screensaver_supported;
|
||||
}
|
||||
|
||||
retro_time_t menu_driver_get_current_time(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
return menu_st->current_time_us;
|
||||
}
|
||||
|
||||
#if defined(HAVE_CG) || defined(HAVE_GLSL) || defined(HAVE_SLANG) || defined(HAVE_HLSL)
|
||||
void menu_driver_set_last_shader_preset_path(const char *path)
|
||||
{
|
||||
@ -3391,28 +2573,6 @@ void menu_driver_set_last_start_content(const char *start_content_path)
|
||||
sizeof(menu->last_start_content.file_name));
|
||||
}
|
||||
|
||||
const char *menu_driver_get_pending_selection(void)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
return menu_st->pending_selection;
|
||||
}
|
||||
|
||||
void menu_driver_set_pending_selection(const char *pending_selection)
|
||||
{
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
char *selection = menu_st->pending_selection;
|
||||
|
||||
/* Reset existing cache */
|
||||
selection[0] = '\0';
|
||||
|
||||
/* If path is empty, do nothing */
|
||||
if (string_is_empty(pending_selection))
|
||||
return;
|
||||
|
||||
strlcpy(selection, pending_selection,
|
||||
sizeof(menu_st->pending_selection));
|
||||
}
|
||||
|
||||
bool menu_driver_ctl(enum rarch_menu_ctl_state state, void *data)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
@ -6679,58 +5839,6 @@ bool gfx_widgets_ready(void)
|
||||
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
static void menu_input_search_cb(void *userdata, const char *str)
|
||||
{
|
||||
const char *label = NULL;
|
||||
unsigned type = MENU_SETTINGS_NONE;
|
||||
struct menu_state *menu_st = menu_state_get_ptr();
|
||||
|
||||
if (string_is_empty(str))
|
||||
goto end;
|
||||
|
||||
/* Determine whether we are currently
|
||||
* viewing a menu list with 'search
|
||||
* filter' support */
|
||||
file_list_get_last(MENU_LIST_GET(menu_st->entries.list, 0),
|
||||
NULL, &label, &type, NULL);
|
||||
|
||||
/* Do not apply search filter if string
|
||||
* consists of a single Latin alphabet
|
||||
* character */
|
||||
if (((str[1] != '\0') || (!ISALPHA(str[0]))) &&
|
||||
menu_driver_search_filter_enabled(label, type))
|
||||
{
|
||||
/* Add search term */
|
||||
if (menu_entries_search_push(str))
|
||||
{
|
||||
bool refresh = false;
|
||||
|
||||
/* Reset navigation pointer */
|
||||
menu_st->selection_ptr = 0;
|
||||
menu_driver_navigation_set(false);
|
||||
|
||||
/* Refresh menu */
|
||||
menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);
|
||||
menu_driver_ctl(RARCH_MENU_CTL_SET_PREVENT_POPULATE, NULL);
|
||||
}
|
||||
}
|
||||
/* Perform a regular search: jump to the
|
||||
* first matching entry */
|
||||
else
|
||||
{
|
||||
size_t idx = 0;
|
||||
|
||||
if (menu_entries_list_search(str, &idx))
|
||||
{
|
||||
menu_st->selection_ptr = idx;
|
||||
menu_driver_navigation_set(true);
|
||||
}
|
||||
}
|
||||
|
||||
end:
|
||||
menu_input_dialog_end();
|
||||
}
|
||||
|
||||
const char *menu_input_dialog_get_label_buffer(void)
|
||||
{
|
||||
struct rarch_state *p_rarch = &rarch_st;
|
||||
|
Loading…
Reference in New Issue
Block a user