# The MIT License (MIT)
#
# Copyright (C) 2026 Scott Duensing
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
# IN THE SOFTWARE.

.section Libraries
.topic lib.listhelp
.title List Helper Library
.toc 0 List Helper Library
.index listhelp
.index widgetDrawDropdownArrow
.index widgetMaxItemLen
.index widgetNavigateIndex
.index widgetDropdownPopupRect
.index widgetPaintPopupList

.h1 List Helper Library

Shared helper routines for dropdown and list-based widget DXEs (ListBox, Dropdown, ComboBox, ListView). Provides dropdown arrow rendering, item measurement, keyboard navigation, popup geometry calculation, popup list painting, type-ahead search, and popup scrollbar hit testing.

Header: listhelp/listHelp.h

Loaded as: bin/libs/listhelp.lib

.h2 Constants

.table
  Constant               Value               Description
  --------               -----               -----------
  DROPDOWN_BTN_WIDTH     16                  Width of the dropdown arrow button in pixels.
  DROPDOWN_MAX_VISIBLE   8                   Maximum number of items visible in a popup list before scrolling.
  POPUP_SCROLLBAR_W      SCROLLBAR_WIDTH     Popup vertical scrollbar width (mirrors the core window-manager scrollbar width).
.endtable

.h2 widgetDrawDropdownArrow

Draw the triangular dropdown arrow glyph centered at a given position.

.code
void widgetDrawDropdownArrow(DisplayT *d, const BlitOpsT *ops,
    int32_t centerX, int32_t centerY, uint32_t color);
.endcode

.table
  Parameter   Description
  ---------   -----------
  d           Display context.
  ops         Blit operations vtable for the active pixel depth.
  centerX     Horizontal center of the arrow in backbuffer coordinates.
  centerY     Vertical center of the arrow in backbuffer coordinates.
  color       Pre-packed pixel color for the arrow.
.endtable

.h2 widgetMaxItemLen

Scan an array of strings and return the length (in characters) of the longest item.

.code
int32_t widgetMaxItemLen(const char **items, int32_t count);
.endcode

.table
  Parameter   Description
  ---------   -----------
  items       Array of null-terminated string pointers.
  count       Number of items in the array.
.endtable

Returns the character length of the longest item, or 0 if count is zero.

.h2 widgetNavigateIndex

Compute a new selected index from a navigation key press. Handles Up, Down, Home, End, Page Up, and Page Down.

.code
int32_t widgetNavigateIndex(int32_t key, int32_t current,
    int32_t count, int32_t pageSize);
.endcode

.table
  Parameter   Description
  ---------   -----------
  key         Keyboard scancode (Up, Down, Home, End, PgUp, PgDn).
  current     Currently selected index.
  count       Total number of items in the list.
  pageSize    Number of visible items (used for PgUp/PgDn step size).
.endtable

Returns the new index, clamped to [0, count-1]. Returns -1 for unrecognized keys so callers can detect whether the key was consumed.

.h2 widgetDropdownPopupRect

Calculate the screen rectangle for a dropdown popup list, positioning it below the owning widget and clamping to screen bounds.

.code
void widgetDropdownPopupRect(WidgetT *w, const BitmapFontT *font,
    int32_t contentH, int32_t itemCount,
    int32_t *popX, int32_t *popY, int32_t *popW, int32_t *popH);
.endcode

.table
  Parameter   Description
  ---------   -----------
  w           The widget that owns the popup (Dropdown, ComboBox, etc.).
  font        Bitmap font used for item text (determines row height).
  contentH    Height of the widget's content area in pixels.
  itemCount   Total number of items in the list.
  popX        Output: popup X position (screen coordinates).
  popY        Output: popup Y position (screen coordinates).
  popW        Output: popup width in pixels.
  popH        Output: popup height in pixels.
.endtable

The popup is sized to show up to DROPDOWN_MAX_VISIBLE items.

.h2 widgetPaintPopupList

Render a popup item list with highlight, scrolling, and beveled border. When itemCount exceeds DROPDOWN_MAX_VISIBLE, draws a vertical scrollbar on the right edge sized according to scrollPos.

.code
void widgetPaintPopupList(DisplayT *d, const BlitOpsT *ops,
    const BitmapFontT *font, const ColorSchemeT *colors,
    int32_t popX, int32_t popY, int32_t popW, int32_t popH,
    const char **items, int32_t itemCount,
    int32_t hoverIdx, int32_t scrollPos);
.endcode

.table
  Parameter   Description
  ---------   -----------
  d           Display context.
  ops         Blit operations vtable.
  font        Bitmap font for rendering item text.
  colors      Color scheme for background, text, and highlight colors.
  popX        Popup X position (from widgetDropdownPopupRect).
  popY        Popup Y position.
  popW        Popup width.
  popH        Popup height.
  items       Array of null-terminated item strings.
  itemCount   Total number of items.
  hoverIdx    Index of the highlighted (hovered/selected) item, or -1 for none.
  scrollPos   Index of the first visible item (scroll offset).
.endtable

.h2 widgetTypeAheadSearch

Case-insensitive type-ahead search. Scans items forward from currentIdx + 1, wrapping around, for the next item whose first character matches ch. Used by list and dropdown widgets to jump to an item based on a single keystroke.

.code
int32_t widgetTypeAheadSearch(char ch, const char **items,
    int32_t itemCount, int32_t currentIdx);
.endcode

.table
  Parameter     Description
  ---------     -----------
  ch            Character to match (case-insensitive).
  items         Array of null-terminated item strings.
  itemCount     Number of items in the array.
  currentIdx    Currently selected index (search starts at currentIdx + 1 and wraps).
.endtable

Returns the index of the next matching item, or -1 if no match is found or itemCount is not positive.

.h2 widgetPopupScrollbarClick

Hit-test a popup scrollbar click. Tests whether the (x, y) coordinate falls on the popup's vertical scrollbar track; if so, updates scrollPos for up/down arrow clicks or page-up/page-down clicks in the trough. No-op on the thumb itself (callers handle drag separately).

.code
bool widgetPopupScrollbarClick(int32_t x, int32_t y,
    int32_t popX, int32_t popY, int32_t popW, int32_t popH,
    int32_t itemCount, int32_t visibleItems,
    int32_t *scrollPos);
.endcode

.table
  Parameter       Description
  ---------       -----------
  x               Click X in the popup's coordinate space.
  y               Click Y in the popup's coordinate space.
  popX            Popup X origin.
  popY            Popup Y origin.
  popW            Popup width.
  popH            Popup height.
  itemCount       Total number of items.
  visibleItems    Number of visible rows in the popup.
  scrollPos       [in/out] Current scroll offset; updated in place when the click hits the scrollbar.
.endtable

Returns true if the click landed on the scrollbar (even if scrollPos was not changed, for example clicking the thumb), false if the click was in the item list area. When itemCount is less than or equal to DROPDOWN_MAX_VISIBLE, always returns false (there is no scrollbar).
