From 089757e33c24d98b598a7598829cda757182d92d Mon Sep 17 00:00:00 2001 From: misteraddons <51079966+misteraddons@users.noreply.github.com> Date: Tue, 29 Jul 2025 22:41:08 -0600 Subject: [PATCH] OSD: Lookahead 0-3 positions when scrolling (#1009) * Lookahead 3 positions when scrolling * Add lookahead position adjustment 0 = disabled 1 = 1 position ahead 2 = 2 positions ahead (default) 3 = 3 positions ahead * Implement lookahead config variable (0-3 positions) --- cfg.cpp | 2 + cfg.h | 1 + file_io.cpp | 152 ++++++++++++++++++++++++++-------------------------- 3 files changed, 80 insertions(+), 75 deletions(-) diff --git a/cfg.cpp b/cfg.cpp index 811118b..6134a36 100644 --- a/cfg.cpp +++ b/cfg.cpp @@ -130,6 +130,7 @@ static const ini_var_t ini_vars[] = { "OSD_LOCK", (void*)(&(cfg.osd_lock)), STRING, 0, sizeof(cfg.osd_lock) - 1 }, { "OSD_LOCK_TIME", (void*)(&(cfg.osd_lock_time)), UINT16, 0, 60 }, { "DEBUG", (void *)(&(cfg.debug)), UINT8, 0, 1 }, + { "LOOKAHEAD", (void *)(&(cfg.lookahead)), UINT8, 0, 3 }, { "MAIN", (void*)(&(cfg.main)), STRING, 0, sizeof(cfg.main) - 1 }, {"VFILTER_INTERLACE_DEFAULT", (void*)(&(cfg.vfilter_interlace_default)), STRING, 0, sizeof(cfg.vfilter_interlace_default) - 1 }, }; @@ -580,6 +581,7 @@ void cfg_parse() cfg.rumble = 1; cfg.wheel_force = 50; cfg.dvi_mode = 2; + cfg.lookahead = 2; cfg.hdr = 0; cfg.hdr_max_nits = 1000; cfg.hdr_avg_nits = 250; diff --git a/cfg.h b/cfg.h index 1789a68..11906cf 100644 --- a/cfg.h +++ b/cfg.h @@ -98,6 +98,7 @@ typedef struct { char osd_lock[25]; uint16_t osd_lock_time; char debug; + uint8_t lookahead; char main[1024]; char vfilter_interlace_default[1023]; } cfg_t; diff --git a/file_io.cpp b/file_io.cpp index 774a732..929381a 100644 --- a/file_io.cpp +++ b/file_io.cpp @@ -1758,7 +1758,8 @@ int ScanDirectory(char* path, int mode, const char *extension, int options, cons if(iSelectedEntry + 1 < flist_nDirEntries()) // scroll within visible items { iSelectedEntry++; - if (iSelectedEntry > iFirstEntry + OsdGetSize() - 1) iFirstEntry = iSelectedEntry - OsdGetSize() + 1; + // Start scrolling when cursor is cfg.lookahead positions from bottom + if (iSelectedEntry > iFirstEntry + OsdGetSize() - (cfg.lookahead + 1)) iFirstEntry = iSelectedEntry - OsdGetSize() + (cfg.lookahead + 1); } else { @@ -1773,45 +1774,105 @@ int ScanDirectory(char* path, int mode, const char *extension, int options, cons if (iSelectedEntry > 0) // scroll within visible items { iSelectedEntry--; - if (iSelectedEntry < iFirstEntry) iFirstEntry = iSelectedEntry; + // Start scrolling when cursor is cfg.lookahead positions from top + if (iSelectedEntry < iFirstEntry + cfg.lookahead) iFirstEntry = iSelectedEntry - cfg.lookahead; + if (iFirstEntry < 0) iFirstEntry = 0; } return 0; } else if (mode == SCANF_NEXT_PAGE) { - if (iSelectedEntry < iFirstEntry + OsdGetSize() - 2) + // Calculate cursor position relative to current page + int cursor_offset = iSelectedEntry - iFirstEntry; + + // Check if we're already on the last page (less than a full page left) + int remaining_entries = flist_nDirEntries() - iFirstEntry; + if (remaining_entries <= OsdGetSize()) { - iSelectedEntry = iFirstEntry + OsdGetSize() - 1; - if (iSelectedEntry >= flist_nDirEntries()) iSelectedEntry = flist_nDirEntries() - 1; + // On last page - allow cursor to go to actual last row + iSelectedEntry = flist_nDirEntries() - 1; + iFirstEntry = flist_nDirEntries() - OsdGetSize(); + if (iFirstEntry < 0) iFirstEntry = 0; } else { - iSelectedEntry += OsdGetSize(); + // Move to next page iFirstEntry += OsdGetSize(); - if (iSelectedEntry >= flist_nDirEntries()) - { - iSelectedEntry = flist_nDirEntries() - 1; - iFirstEntry = iSelectedEntry - OsdGetSize() + 1; - if (iFirstEntry < 0) iFirstEntry = 0; - } - else if (iFirstEntry + OsdGetSize() > flist_nDirEntries()) + if (iFirstEntry >= flist_nDirEntries()) { + // At end, stay on last page iFirstEntry = flist_nDirEntries() - OsdGetSize(); + if (iFirstEntry < 0) iFirstEntry = 0; + iSelectedEntry = flist_nDirEntries() - 1; + } + else + { + // Special handling for top row - jump to cfg.lookahead positions from bottom + if (cursor_offset == 0) + { + iSelectedEntry = iFirstEntry + OsdGetSize() - (cfg.lookahead + 1); + } + else + { + // Maintain relative cursor position, but respect cfg.lookahead buffer from bottom + iSelectedEntry = iFirstEntry + cursor_offset; + + // If cursor would be on bottom cfg.lookahead rows of page, keep it at cfg.lookahead from bottom + if (cursor_offset >= OsdGetSize() - cfg.lookahead) + { + iSelectedEntry = iFirstEntry + OsdGetSize() - (cfg.lookahead + 1); + } + } + + // Ensure we don't go past the end + if (iSelectedEntry >= flist_nDirEntries()) + { + iSelectedEntry = flist_nDirEntries() - 1; + } } } return 0; } else if (mode == SCANF_PREV_PAGE) { - if(iSelectedEntry != iFirstEntry) + // Calculate cursor position relative to current page + int cursor_offset = iSelectedEntry - iFirstEntry; + + // Check if we're already on the first page (less than a full page to go back) + if (iFirstEntry <= OsdGetSize()) { - iSelectedEntry = iFirstEntry; + // On first page - allow cursor to go to actual first row + iSelectedEntry = 0; + iFirstEntry = 0; } else { + // Move to previous page iFirstEntry -= OsdGetSize(); if (iFirstEntry < 0) iFirstEntry = 0; - iSelectedEntry = iFirstEntry; + + // Special handling for bottom row - jump to cfg.lookahead from top + if (cursor_offset == OsdGetSize() - 1) + { + iSelectedEntry = iFirstEntry + cfg.lookahead; + } + else + { + // Maintain relative cursor position, but respect cfg.lookahead buffer from top + iSelectedEntry = iFirstEntry + cursor_offset; + + // If cursor would be on top cfg.lookahead rows of page, keep it at cfg.lookahead from top + if (cursor_offset <= cfg.lookahead - 1) + { + iSelectedEntry = iFirstEntry + cfg.lookahead; + } + } + + // Ensure we don't go past the end + if (iSelectedEntry >= flist_nDirEntries()) + { + iSelectedEntry = flist_nDirEntries() - 1; + } } } else if (mode == SCANF_SET_ITEM) @@ -1838,65 +1899,6 @@ int ScanDirectory(char* path, int mode, const char *extension, int options, cons if (iFirstEntry < 0) iFirstEntry = 0; } } - else if (mode == SCANF_NEXT_CHAR) - { - //DirItem is sorted, so just advance until the first character changes. - //if we reach the end before that don't change anything. - //If we change d_type also consider that 'next'. This means next - //advances through directories, and then advances through files - - int found = -1; - char curChar = toupper(DirItem[iSelectedEntry].altname[0]); - char curdType = DirItem[iSelectedEntry].de.d_type; - for (int i = iSelectedEntry+1; i < flist_nDirEntries(); i++) - { - if (toupper(DirItem[i].altname[0]) != curChar || DirItem[i].de.d_type != curdType) - { - found = i; - break; - } - } - - if (found >= 0) - { - iSelectedEntry = found; - if (iSelectedEntry + (OsdGetSize() / 2) >= flist_nDirEntries()) iFirstEntry = flist_nDirEntries() - OsdGetSize(); - else iFirstEntry = iSelectedEntry - (OsdGetSize()/2) + 1; - if (iFirstEntry < 0) iFirstEntry = 0; - } - } - else if (mode == SCANF_PREV_CHAR) - { - - //Previous seek seeks to the FIRST entry that starts with the previous letter - //Search backward until the first char changes, and then continue looking backward - //until it changes again. - int found = -1; - bool sawChange = false; - char curChar = toupper(DirItem[iSelectedEntry].altname[0]); - char curdType = DirItem[iSelectedEntry].de.d_type; - for (int i = iSelectedEntry-1; i >= 0; i--) - { - if (toupper(DirItem[i].altname[0]) != curChar || DirItem[i].de.d_type != curdType) - { - if (sawChange) - { - found = i+1; - break; - } - sawChange = true; - curChar = toupper(DirItem[i].altname[0]); - } - } - - if (found >= 0) - { - iSelectedEntry = found; - if (iSelectedEntry + (OsdGetSize() / 2) >= flist_nDirEntries()) iFirstEntry = flist_nDirEntries() - OsdGetSize(); - else iFirstEntry = iSelectedEntry - (OsdGetSize()/2) + 1; - if (iFirstEntry < 0) iFirstEntry = 0; - } - } else { //printf("dir scan for key: %x/%c\n", mode, mode);