list.c small cleanup, add simplelist_setline()

add simplelist_setline() to allow literal strings or owner buffer
to be shown in the simplelist

this makes simplelist more versatile by allowing static strings
to be added directly instead of copying into the simplelist buffer
(ie not consuming the simplelist text buffer)

add bounds checking to simplelist_setline/addline
No one has more than SIMPLELIST_MAX_LINES..  right?
-- there are actually a few places this isn't checked..

use new setline function in debug menu

share the simplelist buffer with the list_draw fn for gui_synclist
since they shouldn't be in-use simultaneously we can save some stack

Change-Id: I4a1e64d3a621d326ff094241da55452c0ff746ba
This commit is contained in:
William Wilgus 2024-11-20 12:12:16 -05:00 committed by William Wilgus
parent 505bbcaff5
commit 35a913473e
5 changed files with 133 additions and 141 deletions

View file

@ -1380,7 +1380,7 @@ static int disk_callback(int btn, struct gui_synclist *lists)
}
else if (card->initialized == 0)
{
simplelist_addline("Not Found!");
simplelist_setline("Not Found!");
}
#if (CONFIG_STORAGE & STORAGE_SD)
else /* card->initialized < 0 */
@ -1494,7 +1494,7 @@ static int disk_callback(int btn, struct gui_synclist *lists)
(identify_info[64] & (1<<1)) , &atanums[4*2]);
}
else {
simplelist_addline(
simplelist_setline(
"No PIO mode info");
}
timing_info_present = identify_info[53] & (1<<1);
@ -1504,7 +1504,7 @@ static int disk_callback(int btn, struct gui_synclist *lists)
identify_info[67],
identify_info[68] );
} else {
simplelist_addline(
simplelist_setline(
"No timing info");
}
@ -1521,7 +1521,7 @@ static int disk_callback(int btn, struct gui_synclist *lists)
identify_info[66] );
}
else {
simplelist_addline(
simplelist_setline(
"No MDMA mode info");
}
if (identify_info[53] & (1<<2)) {
@ -1536,8 +1536,7 @@ static int disk_callback(int btn, struct gui_synclist *lists)
(identify_info[88] & (1<<6)) >> 5, &atanums[6*2]);
}
else {
simplelist_addline(
"No UDMA mode info");
simplelist_setline("No UDMA mode info");
}
#endif /* HAVE_ATA_DMA */
timing_info_present = identify_info[53] & (1<<1);
@ -1549,19 +1548,16 @@ static int disk_callback(int btn, struct gui_synclist *lists)
simplelist_addline(
"IORDY disable: %s", i ? "yes" : "no");
} else {
simplelist_addline(
"No timing info");
simplelist_setline("No timing info");
}
simplelist_addline(
"Cluster size: %d bytes", volume_get_cluster_size(IF_MV(0)));
#ifdef HAVE_ATA_DMA
i = ata_get_dma_mode();
if (i == 0) {
simplelist_addline(
"DMA not enabled");
simplelist_setline("DMA not enabled");
} else if (i == 0xff) {
simplelist_addline(
"CE-ATA mode");
simplelist_setline("CE-ATA mode");
} else {
simplelist_addline(
"DMA mode: %s %c",
@ -1759,7 +1755,7 @@ static int ata_smart_callback(int btn, struct gui_synclist *lists)
{
int i;
char buf[SIMPLELIST_MAX_LINELENGTH];
simplelist_addline("Id Name: Current,Worst Raw");
simplelist_setline("Id Name: Current,Worst Raw");
for (i = 0; i < NUMBER_ATA_SMART_ATTRIBUTES; i++)
{
if (ata_smart_attr_to_string(
@ -1936,7 +1932,7 @@ static int database_callback(int btn, struct gui_synclist *lists)
simplelist_addline("Initialized: %s",
stat->initialized ? "Yes" : "No");
simplelist_addline("DB Ready: %s",
simplelist_addline("DB %s: %s", "Ready",
stat->ready ? "Yes" : "No");
simplelist_addline("DB Path: %s", stat->db_path);
simplelist_addline("RAM Cache: %s",
@ -1945,10 +1941,11 @@ static int database_callback(int btn, struct gui_synclist *lists)
stat->ramcache_used, stat->ramcache_allocated);
simplelist_addline("Total entries: %d",
stat->total_entries);
simplelist_addline("Progress: %d%% (%d entries)",
stat->progress, stat->processed_entries);
simplelist_addline("Curfile: %s",
stat->curentry ? stat->curentry : "---");
simplelist_setline("Progress:");
simplelist_addline(" %d%% (%d entries)",
stat->progress, stat->processed_entries);
simplelist_setline("Curfile:");
simplelist_addline(" %s", stat->curentry ? stat->curentry : "---");
simplelist_addline("Commit step: %d",
stat->commit_step);
simplelist_addline("Commit delayed: %s",
@ -2165,7 +2162,7 @@ static int radio_callback(int btn, struct gui_synclist *lists)
#if (CONFIG_TUNER & TEA5767)
struct tea5767_dbg_info nfo;
tea5767_dbg_info(&nfo);
simplelist_addline("Philips regs:");
simplelist_setline("Philips regs:");
simplelist_addline(
" %s: %02X %02X %02X %02X %02X", "Read",
(unsigned)nfo.read_regs[0], (unsigned)nfo.read_regs[1],
@ -2182,7 +2179,7 @@ static int radio_callback(int btn, struct gui_synclist *lists)
{
struct si4700_dbg_info nfo;
si4700_dbg_info(&nfo);
simplelist_addline("SI4700 regs:");
simplelist_setline("SI4700 regs:");
for (int i = 0; i < 16; i += 4) {
simplelist_addline("%02X: %04X %04X %04X %04X",
i, nfo.regs[i], nfo.regs[i+1], nfo.regs[i+2], nfo.regs[i+3]);
@ -2194,7 +2191,7 @@ static int radio_callback(int btn, struct gui_synclist *lists)
{
struct rda5802_dbg_info nfo;
rda5802_dbg_info(&nfo);
simplelist_addline("RDA5802 regs:");
simplelist_setline("RDA5802 regs:");
for (int i = 0; i < 16; i += 4) {
simplelist_addline("%02X: %04X %04X %04X %04X",
i, nfo.regs[i], nfo.regs[i+1], nfo.regs[i+2], nfo.regs[i+3]);
@ -2206,7 +2203,7 @@ static int radio_callback(int btn, struct gui_synclist *lists)
{
struct stfm1000_dbg_info nfo;
stfm1000_dbg_info(&nfo);
simplelist_addline("STFM1000 regs:");
simplelist_setline("STFM1000 regs:");
simplelist_addline("chipid: 0x%lx", nfo.chipid);
}
#endif /* STFM1000 */
@ -2215,7 +2212,7 @@ static int radio_callback(int btn, struct gui_synclist *lists)
{
struct tea5760_dbg_info nfo;
tea5760_dbg_info(&nfo);
simplelist_addline("TEA5760 regs:");
simplelist_setline("TEA5760 regs:");
for (int i = 0; i < 16; i += 4) {
simplelist_addline("%02X: %02X %02X %02X %02X",
i, nfo.read_regs[i], nfo.read_regs[i+1], nfo.read_regs[i+2], nfo.read_regs[i+3]);
@ -2464,69 +2461,49 @@ static bool dbg_scrollwheel(void)
}
#endif
static const char* dbg_talk_get_name(int selected_item, void *data,
char *buffer, size_t buffer_len)
{
struct talk_debug_data *talk_data = data;
switch(selected_item)
{
case 0:
if (talk_data->status != TALK_STATUS_ERR_NOFILE)
snprintf(buffer, buffer_len, "Current voice file: %s",
talk_data->voicefile);
else
buffer = "No voice information available";
break;
case 1:
if (talk_data->status != TALK_STATUS_OK)
snprintf(buffer, buffer_len, "Talk Status: ERR (%i)",
talk_data->status);
else
buffer = "Talk Status: OK";
break;
case 2:
snprintf(buffer, buffer_len, "Number of (empty) clips in voice file: (%d) %d",
talk_data->num_empty_clips, talk_data->num_clips);
break;
case 3:
snprintf(buffer, buffer_len, "Min/Avg/Max size of clips: %d / %d / %d",
talk_data->min_clipsize, talk_data->avg_clipsize, talk_data->max_clipsize);
break;
case 4:
snprintf(buffer, buffer_len, "Memory allocated: %ld.%02ld KB",
talk_data->memory_allocated / 1024, talk_data->memory_allocated % 1024);
break;
case 5:
snprintf(buffer, buffer_len, "Memory used: %ld.%02ld KB",
talk_data->memory_used / 1024, talk_data->memory_used % 1024);
break;
case 6:
snprintf(buffer, buffer_len, "Number of clips in cache: %d",
talk_data->cached_clips);
break;
case 7:
snprintf(buffer, buffer_len, "Cache hits / misses: %d / %d",
talk_data->cache_hits, talk_data->cache_misses);
break;
default:
buffer = "TODO";
break;
}
return buffer;
}
static bool dbg_talk(void)
{
struct simplelist_info list;
struct talk_debug_data data;
if (talk_get_debug_data(&data))
simplelist_info_init(&list, "Voice Information:", 8, &data);
else
simplelist_info_init(&list, "Voice Information:", 2, &data);
talk_get_debug_data(&data);
simplelist_info_init(&list, "Voice Information:", 1, NULL);
list.scroll_all = true;
list.timeout = HZ;
list.get_name = dbg_talk_get_name;
//list.get_name = dbg_talk_get_name;
simplelist_set_line_count(0);
simplelist_setline("Current voice file:");
if (data.status != TALK_STATUS_ERR_NOFILE)
simplelist_addline(" %s", data.voicefile);
else
simplelist_setline(" No voice information available");
if (data.status != TALK_STATUS_OK)
{
simplelist_addline("Talk Status: ERR (%i)",
data.status);
return simplelist_show_list(&list);
}
else
simplelist_setline("Talk Status: OK");
simplelist_setline("Number of (empty) clips in voice file:");
simplelist_addline(" (%d) %d", data.num_empty_clips, data.num_clips);
simplelist_setline("Min/Avg/Max size of clips:");
simplelist_addline(" %d / %d / %d",
data.min_clipsize, data.avg_clipsize, data.max_clipsize);
simplelist_setline("Memory allocated:");
simplelist_addline(" %ld.%02ld KB",
data.memory_allocated / 1024, data.memory_allocated % 1024);
simplelist_addline("Memory used:");
simplelist_addline(" %ld.%02ld KB",
data.memory_used / 1024, data.memory_used % 1024);
simplelist_setline("Number of clips in cache:");
simplelist_addline(" %d", data.cached_clips);
simplelist_setline("Cache hits / misses:");
simplelist_addline("%d / %d", data.cache_hits, data.cache_misses);
return simplelist_show_list(&list);
}
@ -2605,14 +2582,14 @@ static bool dbg_boot_data(void)
if (!boot_data_valid)
{
simplelist_addline("Boot data invalid");
simplelist_setline("Boot data invalid");
simplelist_addline("Magic[0]: %08lx", boot_data.magic[0]);
simplelist_addline("Magic[1]: %08lx", boot_data.magic[1]);
simplelist_addline("Length: %lu", boot_data.length);
}
else
{
simplelist_addline("Boot data valid");
simplelist_setline("Boot data valid");
simplelist_addline("Version: %d", (int)boot_data.version);
if (boot_data.version == 0)
@ -2624,10 +2601,11 @@ static bool dbg_boot_data(void)
simplelist_addline("Boot drive: %d", (int)boot_data.boot_drive);
simplelist_addline("Boot partition: %d", (int)boot_data.boot_partition);
}
simplelist_addline("Boot path: %s%s/%s", root_realpath(), BOOTDIR, BOOTFILE);
simplelist_setline("Boot path:");
simplelist_addline(" %s%s/%s", root_realpath(), BOOTDIR, BOOTFILE);
}
simplelist_addline("Bootdata RAW:");
simplelist_setline("Bootdata RAW:");
for (size_t i = 0; i < boot_data.length; i += 4)
{
simplelist_addline("%02x: %02x %02x %02x %02x", i,
@ -2647,13 +2625,13 @@ static bool dbg_device_data(void)
simplelist_info_init(&info, "Device data", 1, NULL);
simplelist_set_line_count(0);
simplelist_addline("Device data");
simplelist_setline("Device data");
#if defined(EROS_QN)
simplelist_addline("Lcd Version: %d", (int)device_data.lcd_version);
#endif
simplelist_addline("Device data RAW:");
simplelist_setline("Device data RAW:");
for (size_t i = 0; i < device_data.length; i += 4)
{
simplelist_addline("%02x: %02x %02x %02x %02x", i,
@ -2683,7 +2661,7 @@ static bool dbg_syscfg(void) {
bootflash_read(SPI_PORT, 0, syscfg_hdr_size, &syscfg_hdr);
if (syscfg_hdr.magic != SYSCFG_MAGIC) {
simplelist_addline("SCfg magic not found");
simplelist_setline("SCfg magic not found");
bootflash_close(SPI_PORT);
return simplelist_show_list(&info);
}

View file

@ -324,14 +324,15 @@ void list_draw(struct screen *display, struct gui_synclist *list)
/* do the text */
enum themable_icons icon;
unsigned const char *s;
char entry_buffer[MAX_PATH];
extern char simplelist_buffer[SIMPLELIST_MAX_LINES * SIMPLELIST_MAX_LINELENGTH];
/*char entry_buffer[MAX_PATH]; use the buffer from gui/list.c instead */
unsigned char *entry_name;
int line = i - start;
int line_indent = 0;
int style = STYLE_DEFAULT;
bool is_selected = false;
s = list->callback_get_item_name(i, list->data, entry_buffer,
sizeof(entry_buffer));
s = list->callback_get_item_name(i, list->data, simplelist_buffer,
sizeof(simplelist_buffer));
if (P2ID((unsigned char *)s) > VOICEONLY_DELIMITER)
entry_name = "";
else

View file

@ -113,14 +113,15 @@ int list_get_nb_lines(struct gui_synclist *list, enum screen_type screen)
void list_init_item_height(struct gui_synclist *list, enum screen_type screen)
{
struct viewport *vp = list->parent[screen];
int line_height = font_get(vp->font)->height;
#ifdef HAVE_TOUCHSCREEN
/* the 4/12 factor is designed for reasonable item size on a 160dpi screen */
if (global_settings.list_line_padding == -1)
list->line_height[screen] = MAX(lcd_get_dpi()*4/12, (int)font_get(vp->font)->height);
list->line_height[screen] = MAX(lcd_get_dpi()*4/12, line_height);
else
list->line_height[screen] = font_get(vp->font)->height + global_settings.list_line_padding;
list->line_height[screen] = line_height + global_settings.list_line_padding;
#else
list->line_height[screen] = font_get(vp->font)->height;
list->line_height[screen] = line_height;
#endif
}
@ -198,27 +199,21 @@ int gui_list_get_item_offset(struct gui_synclist * gui_list,
struct screen * display,
struct viewport *vp)
{
int item_offset;
int item_offset = gui_list->offset_position[display->screen_type];
if (global_settings.offset_out_of_view)
{
item_offset = gui_list->offset_position[display->screen_type];
}
else
if (!global_settings.offset_out_of_view)
{
int view_width = (vp->width - text_pos);
/* if text is smaller than view */
if (item_width <= vp->width - text_pos)
if (item_width <= view_width)
{
item_offset = 0;
}
/* if text got out of view */
else if (gui_list->offset_position[display->screen_type] >
item_width - (vp->width - text_pos))
else if (item_offset > item_width - view_width)
{
item_offset = item_width - (vp->width - text_pos);
item_offset = item_width - view_width;
}
else
item_offset = gui_list->offset_position[display->screen_type];
}
return item_offset;
@ -290,24 +285,24 @@ static void edge_beep(struct gui_synclist * gui_list, bool wrap)
{
if (gui_list->keyclick)
{
list_speak_item *cb = gui_list->callback_speak_item;
enum system_sound sound = SOUND_LIST_EDGE_BEEP_WRAP;
if (!wrap) /* a bounce */
{
static long last_bounce_tick = 0;
if(TIME_BEFORE(current_tick, last_bounce_tick+HZ/4))
return;
last_bounce_tick = current_tick;
sound = SOUND_LIST_EDGE_BEEP_NOWRAP;
}
/* Next thing the list code will do is go speak the item, doing
a talk_shutup() first. Shutup now so the beep is clearer, and
make sure the subsequent shutup is skipped because otherwise
it'd kill the pcm buffer. */
if (cb) {
if (gui_list->callback_speak_item) {
talk_shutup();
talk_force_enqueue_next();
}
system_sound_play(wrap ? SOUND_LIST_EDGE_BEEP_WRAP : SOUND_LIST_EDGE_BEEP_NOWRAP);
if (cb) {
system_sound_play(sound);
/* On at least x5: if, instead of the above shutup, I insert a
sleep just after the beep_play() call, to delay the subsequent
shutup and talk, then in some cases the beep is not played: if
@ -320,6 +315,8 @@ static void edge_beep(struct gui_synclist * gui_list, bool wrap)
sleep((40*HZ +999)/1000); // FIXME: Is this really needed?
talk_force_shutup();
}
else
system_sound_play(sound);
}
}
@ -381,22 +378,22 @@ void gui_synclist_select_item(struct gui_synclist * gui_list, int item_number)
static void gui_list_select_at_offset(struct gui_synclist * gui_list,
int offset, bool allow_wrap)
{
int new_selection;
if (gui_list->selected_size > 1)
{
offset *= gui_list->selected_size;
}
new_selection = gui_list->selected_item + offset;
int new_selection = gui_list->selected_item + offset;
int remain = (gui_list->nb_items - gui_list->selected_size);
if (new_selection >= gui_list->nb_items)
{
new_selection = allow_wrap ? 0 : gui_list->nb_items - gui_list->selected_size;
new_selection = allow_wrap ? 0 : remain;
edge_beep(gui_list, allow_wrap);
}
else if (new_selection < 0)
{
new_selection = allow_wrap ? gui_list->nb_items - gui_list->selected_size : 0;
new_selection = allow_wrap ? remain : 0;
edge_beep(gui_list, allow_wrap);
}
@ -804,8 +801,9 @@ bool list_do_action(int context, int timeout,
/* Simple use list implementation */
static int simplelist_line_count = 0, simplelist_line_remaining;
static int simplelist_line_pos;
static char simplelist_buffer[SIMPLELIST_MAX_LINES * SIMPLELIST_MAX_LINELENGTH];
static char *simplelist_text[SIMPLELIST_MAX_LINES];
/* buffer shared with bitmap/list code */
char simplelist_buffer[SIMPLELIST_MAX_LINES * SIMPLELIST_MAX_LINELENGTH];
static const char *simplelist_text[SIMPLELIST_MAX_LINES];
/* set the amount of lines shown in the list */
void simplelist_set_line_count(int lines)
{
@ -815,7 +813,7 @@ void simplelist_set_line_count(int lines)
simplelist_line_count = 0;
}
else if (lines < simplelist_line_count) {
char *end = simplelist_text[lines];
const char *end = simplelist_text[lines];
simplelist_line_pos = end - simplelist_buffer;
simplelist_line_remaining = sizeof(simplelist_buffer) - simplelist_line_pos;
simplelist_line_count = lines;
@ -826,6 +824,16 @@ int simplelist_get_line_count(void)
{
return simplelist_line_count;
}
/* set/edit a line pointer in the list. */
void simplelist_setline(const char *text)
{
int line_number = simplelist_line_count++;
if (simplelist_line_count >= SIMPLELIST_MAX_LINES)
simplelist_line_count = 0;
simplelist_text[line_number] = text;
}
/* add/edit a line in the list.
if line_number > number of lines shown it adds the line,
else it edits the line */
@ -833,11 +841,12 @@ void simplelist_addline(const char *fmt, ...)
{
va_list ap;
size_t len = simplelist_line_remaining;
int line_number = simplelist_line_count++;
simplelist_text[line_number] = &simplelist_buffer[simplelist_line_pos];
char *bufpos = &simplelist_buffer[simplelist_line_pos];
simplelist_setline(bufpos);
va_start(ap, fmt);
len = vsnprintf(simplelist_text[line_number], simplelist_line_remaining, fmt, ap);
len = vsnprintf(bufpos, simplelist_line_remaining, fmt, ap);
va_end(ap);
len++;
simplelist_line_remaining -= len;
@ -850,6 +859,8 @@ static const char* simplelist_static_getname(int item,
size_t buffer_len)
{
(void)data; (void)buffer; (void)buffer_len;
/* Note: buffer shouldn't be used..
* simplelist_buffer[] is already referenced by simplelist_text[] */
return simplelist_text[item];
}
@ -858,10 +869,18 @@ bool simplelist_show_list(struct simplelist_info *info)
struct gui_synclist lists;
int action, old_line_count = simplelist_line_count;
list_get_name *getname;
int line_count;
if (info->get_name)
{
getname = info->get_name;
line_count = info->count;
}
else
{
getname = simplelist_static_getname;
line_count = simplelist_line_count;
}
FOR_NB_SCREENS(i)
viewportmanager_theme_enable(i, !info->hide_theme, NULL);
@ -871,13 +890,11 @@ bool simplelist_show_list(struct simplelist_info *info)
if (info->title)
gui_synclist_set_title(&lists, info->title, info->title_icon);
if (info->get_icon)
gui_synclist_set_icon_callback(&lists, info->get_icon);
if (info->get_talk)
gui_synclist_set_voice_callback(&lists, info->get_talk);
gui_synclist_set_icon_callback(&lists, info->get_icon);
gui_synclist_set_voice_callback(&lists, info->get_talk);
#ifdef HAVE_LCD_COLOR
if (info->get_color)
gui_synclist_set_color_callback(&lists, info->get_color);
gui_synclist_set_color_callback(&lists, info->get_color);
if (info->selection_color)
gui_synclist_set_sel_color(&lists, info->selection_color);
#endif
@ -885,11 +902,7 @@ bool simplelist_show_list(struct simplelist_info *info)
if (info->action_callback)
info->action_callback(ACTION_REDRAW, &lists);
if (info->get_name == NULL)
gui_synclist_set_nb_items(&lists,
simplelist_line_count*info->selection_size);
else
gui_synclist_set_nb_items(&lists, info->count*info->selection_size);
gui_synclist_set_nb_items(&lists, line_count*info->selection_size);
gui_synclist_select_item(&lists, info->selection);

View file

@ -313,7 +313,7 @@ void simplelist_set_line_count(int lines);
int simplelist_get_line_count(void);
/* add a line in the list. */
void simplelist_addline(const char *fmt, ...) ATTRIBUTE_PRINTF(1,2);
void simplelist_setline(const char *text);
/* setup the info struct. members not setup in this function need to be assigned manually
members set in this function:
info.selection_size = 1;

View file

@ -354,19 +354,19 @@ bool dbg_skin_engine(void)
{
simplelist_addline("Skin ID: %d, %zd allocations",
i, stats->buflib_handles);
simplelist_addline("\tskin: %zd bytes",
stats->tree_size);
simplelist_addline("\tImages: %zd bytes",
stats->images_size);
simplelist_addline("\tTotal: %zd bytes",
stats->tree_size + stats->images_size);
simplelist_addline("\t%s: %zd bytes",
"Skin", stats->tree_size);
simplelist_addline("\t%s: %zd bytes",
"Images", stats->images_size);
simplelist_addline("\t%s: %zd bytes",
"Total", stats->tree_size + stats->images_size);
total += stats->tree_size + stats->images_size;
}
}
}
simplelist_addline("Skin total usage: %d bytes", total);
simplelist_addline("%s usage: %d bytes", "Skin total", total);
#if defined(HAVE_BACKDROP_IMAGE)
simplelist_addline("Backdrop Images:");
simplelist_setline("Backdrop Images:");
i = 0;
while (skin_backdrop_get_debug(i++, &path, &ref_count, &bytes)) {
if (ref_count > 0) {
@ -379,7 +379,7 @@ bool dbg_skin_engine(void)
total += bytes;
}
}
simplelist_addline("Total usage: %d bytes", total);
simplelist_addline("%s usage: %d bytes", "Total", total);
#endif
return simplelist_show_list(&info);
}