DVX_GUI/docs/dvx_api_reference.html
2026-04-06 22:25:06 -05:00

2933 lines
107 KiB
HTML

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="ASCII">
<title>DVX GUI API Reference</title>
<style>
body {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
margin: 0;
padding: 0;
background: #f8f8f8;
color: #222;
line-height: 1.6;
}
header {
background: #1a3a5c;
color: #fff;
padding: 24px 40px;
}
header h1 {
margin: 0;
font-size: 28px;
}
header p {
margin: 4px 0 0 0;
color: #b0c8e0;
font-size: 14px;
}
.container {
max-width: 1100px;
margin: 0 auto;
padding: 20px 40px 60px 40px;
}
nav {
background: #fff;
border: 1px solid #d0d0d0;
padding: 16px 24px;
margin-bottom: 32px;
}
nav h2 {
margin: 0 0 10px 0;
font-size: 18px;
color: #1a3a5c;
}
nav ul {
margin: 0;
padding: 0 0 0 20px;
}
nav li {
margin: 3px 0;
}
nav a {
color: #1a3a5c;
text-decoration: none;
}
nav a:hover {
text-decoration: underline;
}
.layer {
margin-bottom: 40px;
}
.layer-header {
background: #1a3a5c;
color: #fff;
padding: 10px 20px;
font-size: 20px;
margin: 0;
}
.layer-desc {
background: #e8eef4;
border: 1px solid #d0d0d0;
border-top: none;
padding: 10px 20px;
font-size: 14px;
color: #333;
margin: 0 0 2px 0;
}
.func {
background: #fff;
border: 1px solid #d0d0d0;
margin-bottom: 12px;
padding: 0;
}
.func-sig {
background: #f0f0f0;
padding: 10px 16px;
font-family: "Consolas", "Courier New", monospace;
font-size: 13px;
border-bottom: 1px solid #d0d0d0;
overflow-x: auto;
white-space: pre;
}
.func-body {
padding: 10px 16px;
font-size: 14px;
}
.func-body p {
margin: 4px 0;
}
.func-body .label {
font-weight: bold;
color: #555;
}
.params {
margin: 4px 0 4px 0;
padding: 0;
}
.params dt {
font-family: "Consolas", "Courier New", monospace;
font-size: 13px;
color: #1a3a5c;
margin-top: 4px;
}
.params dd {
margin: 0 0 0 20px;
font-size: 13px;
}
.type-section {
background: #fff;
border: 1px solid #d0d0d0;
margin-bottom: 12px;
}
.type-header {
background: #f0f0f0;
padding: 8px 16px;
font-family: "Consolas", "Courier New", monospace;
font-size: 13px;
font-weight: bold;
border-bottom: 1px solid #d0d0d0;
}
.type-body {
padding: 10px 16px;
font-size: 14px;
}
.define-table {
width: 100%;
border-collapse: collapse;
font-size: 13px;
margin: 6px 0;
}
.define-table th {
text-align: left;
background: #f0f0f0;
padding: 4px 10px;
border: 1px solid #d0d0d0;
}
.define-table td {
padding: 4px 10px;
border: 1px solid #d0d0d0;
font-family: "Consolas", "Courier New", monospace;
}
.define-table td:last-child {
font-family: "Segoe UI", Tahoma, Geneva, Verdana, sans-serif;
}
h3 {
color: #1a3a5c;
margin: 20px 0 8px 0;
font-size: 16px;
}
footer {
text-align: center;
color: #888;
font-size: 12px;
padding: 20px;
border-top: 1px solid #d0d0d0;
}
</style>
</head>
<body>
<header>
<h1>DVX GUI API Reference</h1>
<p>DOS Visual eXecutive -- Complete public API documentation generated from source headers</p>
</header>
<div class="container">
<!-- ============================================================ -->
<!-- TABLE OF CONTENTS -->
<!-- ============================================================ -->
<nav>
<h2>Table of Contents</h2>
<ul>
<li><a href="#types">dvxTypes.h -- Shared Type Definitions</a></li>
<li><a href="#cursor">dvxCursor.h -- Cursor Definitions</a></li>
<li><a href="#video">dvxVideo.h -- Layer 1: VESA VBE Video Backend</a></li>
<li><a href="#draw">dvxDraw.h -- Layer 2: Drawing Primitives</a></li>
<li><a href="#comp">dvxComp.h -- Layer 3: Dirty Rectangle Compositor</a></li>
<li><a href="#wm">dvxWm.h -- Layer 4: Window Manager</a></li>
<li><a href="#app">dvxApp.h -- Layer 5: Application API</a></li>
<li><a href="#widget">dvxWidget.h -- Widget System</a></li>
</ul>
</nav>
<!-- ============================================================ -->
<!-- dvxTypes.h -->
<!-- ============================================================ -->
<div class="layer" id="types">
<h2 class="layer-header">dvxTypes.h -- Shared Type Definitions</h2>
<p class="layer-desc">
Central type definitions shared across all five layers of the DVX GUI stack.
Every header includes this file. Contains no function definitions -- only structs,
enums, typedefs, and compile-time constants.
</p>
<h3>Core Structures</h3>
<div class="type-section">
<div class="type-header">PixelFormatT</div>
<div class="type-body">
Describes the pixel encoding for the active VESA video mode. Populated once at
startup from the VBE mode info block, then treated as read-only.
<dl class="params">
<dt>int32_t bitsPerPixel</dt><dd>8, 15, 16, or 32</dd>
<dt>int32_t bytesPerPixel</dt><dd>1, 2, 2, or 4</dd>
<dt>uint32_t redMask, greenMask, blueMask</dt><dd>Bitmasks for each color channel (e.g. 0xF800 for red in 565)</dd>
<dt>int32_t redShift, greenShift, blueShift</dt><dd>Bit position of each color field</dd>
<dt>int32_t redBits, greenBits, blueBits</dt><dd>Number of bits per channel (5, 6, 8, etc.)</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">DisplayT</div>
<div class="type-body">
Single display context passed by pointer through every layer. All drawing targets
the backBuf; only dirty rects are flushed to lfb.
<dl class="params">
<dt>int32_t width, height</dt><dd>Screen dimensions in pixels</dd>
<dt>int32_t pitch</dt><dd>Bytes per scanline</dd>
<dt>PixelFormatT format</dt><dd>Active pixel format</dd>
<dt>uint8_t *lfb</dt><dd>Mapped linear framebuffer (VESA LFB)</dd>
<dt>uint8_t *backBuf</dt><dd>System RAM backbuffer</dd>
<dt>uint8_t *palette</dt><dd>768 bytes for 8-bit mode, NULL otherwise</dd>
<dt>int32_t clipX, clipY, clipW, clipH</dt><dd>Current clip rectangle</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">RectT</div>
<div class="type-body">
Rectangle in origin + extent form. Used throughout the compositor, window manager,
and widget layout engine.
<dl class="params">
<dt>int32_t x, y</dt><dd>Top-left corner</dd>
<dt>int32_t w, h</dt><dd>Width and height</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">BlitOpsT</div>
<div class="type-body">
Vtable for hot-path span operations. Resolved at init time based on pixel depth.
On DOS, these dispatch to hand-written asm (rep stosl / rep movsd).
<dl class="params">
<dt>SpanFillFnT spanFill</dt><dd>Fill a horizontal span with a solid color</dd>
<dt>SpanCopyFnT spanCopy</dt><dd>Copy a horizontal span between buffers</dd>
<dt>int32_t bytesPerPixel</dt><dd>Bytes per pixel for the active mode</dd>
<dt>int32_t pitch</dt><dd>Bytes per scanline</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">BevelStyleT</div>
<div class="type-body">
Bevel drawing parameters. Swapping highlight/shadow flips raised vs. sunken appearance.
<dl class="params">
<dt>uint32_t highlight</dt><dd>Lighter color (top/left edges)</dd>
<dt>uint32_t shadow</dt><dd>Darker color (bottom/right edges)</dd>
<dt>uint32_t face</dt><dd>Interior fill color (0 = no fill)</dd>
<dt>int32_t width</dt><dd>Border thickness in pixels (typically 2)</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">BitmapFontT</div>
<div class="type-body">
Fixed-width 8-pixel-wide bitmap font descriptor. One size provided: 8x16
(standard VGA ROM font, CP437 encoding).
<dl class="params">
<dt>int32_t charWidth</dt><dd>Fixed width per glyph (always 8)</dd>
<dt>int32_t charHeight</dt><dd>Glyph height (14 or 16)</dd>
<dt>int32_t firstChar</dt><dd>ASCII code of first glyph (typically 0)</dd>
<dt>int32_t numChars</dt><dd>Number of glyphs (typically 256)</dd>
<dt>const uint8_t *glyphData</dt><dd>Packed 1bpp data, charHeight bytes per glyph</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">ColorSchemeT</div>
<div class="type-body">
All UI colors pre-packed into display pixel format at init time. Theme support
is achieved by swapping this struct.
<dl class="params">
<dt>uint32_t desktop</dt><dd>Desktop background color</dd>
<dt>uint32_t windowFace</dt><dd>Window body / chrome face</dd>
<dt>uint32_t windowHighlight</dt><dd>Bevel highlight (top/left edge)</dd>
<dt>uint32_t windowShadow</dt><dd>Bevel shadow (bottom/right edge)</dd>
<dt>uint32_t activeTitleBg, activeTitleFg</dt><dd>Focused window title bar</dd>
<dt>uint32_t inactiveTitleBg, inactiveTitleFg</dt><dd>Unfocused window title bar</dd>
<dt>uint32_t contentBg, contentFg</dt><dd>Window content area default colors</dd>
<dt>uint32_t menuBg, menuFg</dt><dd>Menu bar and popup background/text</dd>
<dt>uint32_t menuHighlightBg, menuHighlightFg</dt><dd>Menu item highlight</dd>
<dt>uint32_t buttonFace</dt><dd>Button face color</dd>
<dt>uint32_t scrollbarBg, scrollbarFg, scrollbarTrough</dt><dd>Scrollbar element colors</dd>
<dt>uint32_t cursorFg, cursorBg</dt><dd>Mouse cursor colors</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">ColorIdE</div>
<div class="type-body">
Enum for addressing individual colors in ColorSchemeT. Order matches struct field order.
Values: ColorDesktopE, ColorWindowFaceE, ColorWindowHighlightE, ColorWindowShadowE,
ColorActiveTitleBgE, ColorActiveTitleFgE, ColorInactiveTitleBgE, ColorInactiveTitleFgE,
ColorContentBgE, ColorContentFgE, ColorMenuBgE, ColorMenuFgE, ColorMenuHighlightBgE,
ColorMenuHighlightFgE, ColorButtonFaceE, ColorScrollbarBgE, ColorScrollbarFgE,
ColorScrollbarTroughE, ColorCursorFgE, ColorCursorBgE, ColorCountE.
</div>
</div>
<div class="type-section">
<div class="type-header">DirtyListT</div>
<div class="type-body">
Fixed-capacity list of dirty rectangles. Dynamic array, grows on demand.
<dl class="params">
<dt>RectT *rects</dt><dd>Dynamic array of dirty rectangles</dd>
<dt>int32_t count</dt><dd>Current number of dirty rects</dd>
<dt>int32_t cap</dt><dd>Allocated capacity</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">WindowT</div>
<div class="type-body">
Central window object. Each window owns a persistent content backbuffer and
receives events through callback function pointers.
<dl class="params">
<dt>int32_t id</dt><dd>Unique window identifier</dd>
<dt>int32_t appId</dt><dd>Shell app ID (0 = shell itself)</dd>
<dt>int32_t x, y, w, h</dt><dd>Outer frame position and dimensions</dd>
<dt>int32_t contentX, contentY, contentW, contentH</dt><dd>Content area inset from frame</dd>
<dt>char title[MAX_TITLE_LEN]</dt><dd>Window title text (max 128 chars)</dd>
<dt>bool visible, focused, minimized, maximized, resizable, modal</dt><dd>Window state flags</dd>
<dt>bool contentDirty</dt><dd>true when contentBuf has changed since last icon refresh</dd>
<dt>bool needsPaint</dt><dd>true until first onPaint call (auto-paint on next frame)</dd>
<dt>int32_t maxW, maxH</dt><dd>Maximum dimensions (WM_MAX_FROM_SCREEN = use screen size)</dd>
<dt>int32_t preMaxX, preMaxY, preMaxW, preMaxH</dt><dd>Saved geometry before maximize (for restore)</dd>
<dt>uint8_t *contentBuf</dt><dd>Per-window content backbuffer</dd>
<dt>int32_t contentPitch</dt><dd>Content buffer bytes per row</dd>
<dt>uint8_t *iconData</dt><dd>Icon pixel data (display format), NULL if none</dd>
<dt>int32_t iconW, iconH, iconPitch</dt><dd>Icon image dimensions and row pitch</dd>
<dt>MenuBarT *menuBar</dt><dd>Menu bar (NULL if no menus)</dd>
<dt>ScrollbarT *vScroll, *hScroll</dt><dd>Scrollbars (NULL if not present)</dd>
<dt>struct WidgetT *widgetRoot</dt><dd>Widget tree root (NULL if no widgets)</dd>
<dt>MenuT *contextMenu</dt><dd>Right-click context menu (NULL if none)</dd>
<dt>AccelTableT *accelTable</dt><dd>Keyboard accelerator table (NULL if none)</dd>
<dt>void *userData</dt><dd>Application-defined data pointer</dd>
</dl>
<p><span class="label">Callbacks:</span></p>
<dl class="params">
<dt>onPaint(WindowT *win, RectT *dirtyArea)</dt><dd>Content repaint requested</dd>
<dt>onKey(WindowT *win, int32_t key, int32_t mod)</dt><dd>Key press</dd>
<dt>onKeyUp(WindowT *win, int32_t scancode, int32_t mod)</dt><dd>Key release</dd>
<dt>onMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons)</dt><dd>Mouse event (content-relative coords)</dd>
<dt>onResize(WindowT *win, int32_t newW, int32_t newH)</dt><dd>Window resized</dd>
<dt>onClose(WindowT *win)</dt><dd>Close requested</dd>
<dt>onMenu(WindowT *win, int32_t menuId)</dt><dd>Menu item or accelerator activated</dd>
<dt>onScroll(WindowT *win, ScrollbarOrientE orient, int32_t value)</dt><dd>Scrollbar value changed</dd>
<dt>onCursorQuery(WindowT *win, int32_t x, int32_t y)</dt><dd>Return CURSOR_* for hit position</dd>
<dt>onFocus(WindowT *win)</dt><dd>Window gained focus</dd>
<dt>onBlur(WindowT *win)</dt><dd>Window lost focus</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">WindowStackT</div>
<div class="type-body">
Z-ordered window stack (front-to-back: index count-1 is topmost). Owns system-wide
drag/resize/scroll interaction state.
<dl class="params">
<dt>WindowT **windows</dt><dd>Dynamic array of window pointers</dd>
<dt>int32_t count, cap</dt><dd>Current count and allocated capacity</dd>
<dt>int32_t focusedIdx</dt><dd>Stack index of focused window</dd>
<dt>int32_t dragWindow, dragOffX, dragOffY</dt><dd>Active drag state</dd>
<dt>int32_t resizeWindow, resizeEdge</dt><dd>Active resize state</dd>
<dt>int32_t scrollWindow, scrollOrient, scrollDragOff</dt><dd>Active scroll drag state</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">MenuT / MenuItemT / MenuBarT</div>
<div class="type-body">
Menu system types. Fixed-size label buffers (MAX_MENU_LABEL = 32). Cascading
submenus supported via MenuItemT.subMenu pointer.
<dl class="params">
<dt>MenuItemT.label</dt><dd>Item text (supports &amp; accelerator markers)</dd>
<dt>MenuItemT.id</dt><dd>Application-defined command ID</dd>
<dt>MenuItemT.type</dt><dd>MenuItemNormalE, MenuItemCheckE, or MenuItemRadioE</dd>
<dt>MenuItemT.separator</dt><dd>true = horizontal divider line</dd>
<dt>MenuItemT.enabled, checked</dt><dd>Item state</dd>
<dt>MenuItemT.subMenu</dt><dd>Child menu for cascading (NULL if leaf)</dd>
<dt>MenuBarT.activeIdx</dt><dd>Open popup index (-1 = none)</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">ScrollbarT</div>
<div class="type-body">
Window-level scrollbar state. Managed by the WM layer, drawn after content.
<dl class="params">
<dt>ScrollbarOrientE orient</dt><dd>ScrollbarVerticalE or ScrollbarHorizontalE</dd>
<dt>int32_t min, max</dt><dd>Scroll range</dd>
<dt>int32_t value</dt><dd>Current position</dd>
<dt>int32_t pageSize</dt><dd>Visible portion (for proportional thumb sizing)</dd>
<dt>int32_t x, y, length</dt><dd>Computed screen position and track length</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">AccelTableT / AccelEntryT</div>
<div class="type-body">
Per-window keyboard accelerator table. Entries are matched against keystrokes
in the event loop and fire onMenu(cmdId) on match.
<dl class="params">
<dt>AccelEntryT.key</dt><dd>ASCII character or KEY_Fxx constant</dd>
<dt>AccelEntryT.modifiers</dt><dd>Bitmask of ACCEL_CTRL, ACCEL_SHIFT, ACCEL_ALT</dd>
<dt>AccelEntryT.cmdId</dt><dd>Command ID passed to onMenu</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">VideoModeInfoT</div>
<div class="type-body">
Describes an available video mode (enumerated at init).
<dl class="params">
<dt>int32_t w, h</dt><dd>Resolution</dd>
<dt>int32_t bpp</dt><dd>Bits per pixel</dd>
</dl>
</div>
</div>
<div class="type-section">
<div class="type-header">CursorT</div>
<div class="type-body">
Software-rendered 16x16 cursor using AND/XOR mask encoding.
<dl class="params">
<dt>int32_t width, height</dt><dd>Cursor dimensions (always 16x16)</dd>
<dt>int32_t hotX, hotY</dt><dd>Hot spot coordinates</dd>
<dt>const uint16_t *andMask</dt><dd>AND mask (0 = draw pixel, 1 = transparent)</dd>
<dt>const uint16_t *xorData</dt><dd>XOR data (0 = black, 1 = white where AND = 0)</dd>
</dl>
</div>
</div>
<h3>Bevel Convenience Macros</h3>
<table class="define-table">
<tr><th>Macro</th><th>Description</th></tr>
<tr><td>BEVEL_RAISED(cs, bw)</td><td>Raised bevel style from a ColorSchemeT pointer and border width</td></tr>
<tr><td>BEVEL_SUNKEN(cs, face, bw)</td><td>Sunken bevel style with explicit face color</td></tr>
<tr><td>BEVEL_TROUGH(cs)</td><td>1px sunken trough (for scrollbar tracks)</td></tr>
<tr><td>BEVEL_SB_BUTTON(cs)</td><td>1px raised scrollbar button</td></tr>
</table>
<h3>Chrome Constants</h3>
<table class="define-table">
<tr><th>Define</th><th>Value</th><th>Description</th></tr>
<tr><td>CHROME_BORDER_WIDTH</td><td>4</td><td>Outer frame border width</td></tr>
<tr><td>CHROME_TITLE_HEIGHT</td><td>20</td><td>Title bar height</td></tr>
<tr><td>CHROME_TITLE_PAD</td><td>4</td><td>Title text padding</td></tr>
<tr><td>CHROME_INNER_BORDER</td><td>2</td><td>Inner chrome border</td></tr>
<tr><td>CHROME_MENU_HEIGHT</td><td>20</td><td>Menu bar height</td></tr>
<tr><td>CHROME_TOTAL_TOP</td><td>26</td><td>Total inset from top of frame to content</td></tr>
<tr><td>CHROME_TOTAL_SIDE</td><td>6</td><td>Total inset from side of frame to content</td></tr>
<tr><td>CHROME_TOTAL_BOTTOM</td><td>6</td><td>Total inset from bottom of frame to content</td></tr>
<tr><td>CHROME_CLOSE_BTN_SIZE</td><td>16</td><td>Close button gadget size</td></tr>
</table>
<h3>Hit Test Constants</h3>
<table class="define-table">
<tr><th>Define</th><th>Value</th><th>Description</th></tr>
<tr><td>HIT_CONTENT</td><td>0</td><td>Content area</td></tr>
<tr><td>HIT_TITLE</td><td>1</td><td>Title bar</td></tr>
<tr><td>HIT_CLOSE</td><td>2</td><td>Close gadget</td></tr>
<tr><td>HIT_RESIZE</td><td>3</td><td>Resize border</td></tr>
<tr><td>HIT_MENU</td><td>4</td><td>Menu bar</td></tr>
<tr><td>HIT_VSCROLL</td><td>5</td><td>Vertical scrollbar</td></tr>
<tr><td>HIT_HSCROLL</td><td>6</td><td>Horizontal scrollbar</td></tr>
<tr><td>HIT_MINIMIZE</td><td>7</td><td>Minimize gadget</td></tr>
<tr><td>HIT_MAXIMIZE</td><td>8</td><td>Maximize gadget</td></tr>
<tr><td>HIT_NONE</td><td>-1</td><td>No window hit (desktop)</td></tr>
</table>
<h3>Mouse Button Flags</h3>
<table class="define-table">
<tr><th>Define</th><th>Value</th><th>Description</th></tr>
<tr><td>MOUSE_LEFT</td><td>1</td><td>Left mouse button</td></tr>
<tr><td>MOUSE_RIGHT</td><td>2</td><td>Right mouse button</td></tr>
<tr><td>MOUSE_MIDDLE</td><td>4</td><td>Middle mouse button</td></tr>
</table>
<h3>Accelerator Modifier Flags</h3>
<table class="define-table">
<tr><th>Define</th><th>Value</th><th>Description</th></tr>
<tr><td>ACCEL_SHIFT</td><td>0x03</td><td>Shift key (matches BIOS shift state bits)</td></tr>
<tr><td>ACCEL_CTRL</td><td>0x04</td><td>Ctrl key</td></tr>
<tr><td>ACCEL_ALT</td><td>0x08</td><td>Alt key</td></tr>
</table>
<h3>Extended Key Codes</h3>
<table class="define-table">
<tr><th>Define</th><th>Description</th></tr>
<tr><td>KEY_F1 .. KEY_F12</td><td>Function keys (scancode | 0x100)</td></tr>
<tr><td>KEY_INSERT</td><td>Insert key</td></tr>
<tr><td>KEY_DELETE</td><td>Delete key</td></tr>
<tr><td>KEY_HOME</td><td>Home key</td></tr>
<tr><td>KEY_END</td><td>End key</td></tr>
<tr><td>KEY_PGUP</td><td>Page Up key</td></tr>
<tr><td>KEY_PGDN</td><td>Page Down key</td></tr>
</table>
<h3>Resize Edge Flags</h3>
<table class="define-table">
<tr><th>Define</th><th>Value</th><th>Description</th></tr>
<tr><td>RESIZE_NONE</td><td>0</td><td>No resize edge</td></tr>
<tr><td>RESIZE_LEFT</td><td>1</td><td>Left edge</td></tr>
<tr><td>RESIZE_RIGHT</td><td>2</td><td>Right edge</td></tr>
<tr><td>RESIZE_TOP</td><td>4</td><td>Top edge</td></tr>
<tr><td>RESIZE_BOTTOM</td><td>8</td><td>Bottom edge (combinable via OR for corners)</td></tr>
</table>
<h3>Utility Macros</h3>
<table class="define-table">
<tr><th>Macro</th><th>Description</th></tr>
<tr><td>DVX_MIN(a, b)</td><td>Return the smaller of two values</td></tr>
<tr><td>DVX_MAX(a, b)</td><td>Return the larger of two values</td></tr>
</table>
</div>
<!-- ============================================================ -->
<!-- dvxCursor.h -->
<!-- ============================================================ -->
<div class="layer" id="cursor">
<h2 class="layer-header">dvxCursor.h -- Cursor Definitions</h2>
<p class="layer-desc">
Embedded 16x16 mouse cursor bitmaps compiled as static const data. No external cursor
files. Uses the standard AND/XOR mask encoding from the IBM VGA hardware cursor spec.
</p>
<h3>Cursor Shape IDs</h3>
<table class="define-table">
<tr><th>Define</th><th>Value</th><th>Description</th></tr>
<tr><td>CURSOR_ARROW</td><td>0</td><td>Standard arrow (hot spot at tip)</td></tr>
<tr><td>CURSOR_RESIZE_H</td><td>1</td><td>Horizontal resize (left/right arrows)</td></tr>
<tr><td>CURSOR_RESIZE_V</td><td>2</td><td>Vertical resize (up/down arrows)</td></tr>
<tr><td>CURSOR_RESIZE_DIAG_NWSE</td><td>3</td><td>NW-SE diagonal resize</td></tr>
<tr><td>CURSOR_RESIZE_DIAG_NESW</td><td>4</td><td>NE-SW diagonal resize</td></tr>
<tr><td>CURSOR_BUSY</td><td>5</td><td>Hourglass (wait)</td></tr>
<tr><td>CURSOR_CROSSHAIR</td><td>6</td><td>Crosshair for placement</td></tr>
<tr><td>CURSOR_COUNT</td><td>7</td><td>Total number of cursor shapes</td></tr>
</table>
<h3>Data</h3>
<div class="type-section">
<div class="type-header">dvxCursors[CURSOR_COUNT]</div>
<div class="type-body">
Static const array of CursorT structs, indexed by CURSOR_xxx constants.
Each entry includes the AND mask, XOR data, dimensions, and hot spot coordinates.
</div>
</div>
</div>
<!-- ============================================================ -->
<!-- dvxVideo.h -->
<!-- ============================================================ -->
<div class="layer" id="video">
<h2 class="layer-header">dvxVideo.h -- Layer 1: VESA VBE Video Backend</h2>
<p class="layer-desc">
The lowest layer. Responsible for VESA VBE mode negotiation, LFB mapping via DPMI,
system RAM backbuffer allocation, pixel format discovery, and color packing.
LFB-only design: bank switching is deliberately unsupported.
</p>
<div class="func">
<div class="func-sig">int32_t videoInit(DisplayT *d, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);</div>
<div class="func-body">
<p>Probe VBE for a mode matching the requested resolution and depth, enable it, map
the LFB into DPMI linear address space, and allocate a system RAM backbuffer.
preferredBpp is a hint; the closest available depth is used if an exact match is not found.</p>
<dl class="params">
<dt>d</dt><dd>Display context to initialize</dd>
<dt>requestedW, requestedH</dt><dd>Desired screen resolution</dd>
<dt>preferredBpp</dt><dd>Preferred bits per pixel (8, 15, 16, or 32)</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, negative on failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">void videoShutdown(DisplayT *d);</div>
<div class="func-body">
<p>Restore VGA text mode (mode 3), unmap the LFB, and free the backbuffer.
Safe to call even if videoInit() failed.</p>
<dl class="params">
<dt>d</dt><dd>Display context to shut down</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">uint32_t packColor(const DisplayT *d, uint8_t r, uint8_t g, uint8_t b);</div>
<div class="func-body">
<p>Pack an RGB triplet into the display's native pixel format. For direct-color modes
(15/16/32 bpp), returns a packed pixel value using shift/mask fields. For 8-bit mode,
returns the nearest palette index via Euclidean distance in RGB space.</p>
<dl class="params">
<dt>d</dt><dd>Display context (provides pixel format)</dd>
<dt>r, g, b</dt><dd>Color components (0-255)</dd>
</dl>
<p><span class="label">Returns:</span> Native pixel value suitable for direct framebuffer write</p>
</div>
</div>
<div class="func">
<div class="func-sig">void setClipRect(DisplayT *d, int32_t x, int32_t y, int32_t w, int32_t h);</div>
<div class="func-body">
<p>Set the clip rectangle on the display. All subsequent draw operations clip to this rectangle.
The caller must save and restore the clip rect around scoped operations.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>x, y, w, h</dt><dd>Clip rectangle in screen coordinates</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void resetClipRect(DisplayT *d);</div>
<div class="func-body">
<p>Reset the clip rectangle to the full display dimensions.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
</dl>
</div>
</div>
</div>
<!-- ============================================================ -->
<!-- dvxDraw.h -->
<!-- ============================================================ -->
<div class="layer" id="draw">
<h2 class="layer-header">dvxDraw.h -- Layer 2: Drawing Primitives</h2>
<p class="layer-desc">
All 2D drawing operations: rectangle fills, bitmap blits, text rendering, bevels, lines,
and cursor rendering. Every function draws into the display's backbuffer and clips to
the current clip rectangle. This layer is stateless beyond the clip rect on DisplayT.
</p>
<div class="func">
<div class="func-sig">void drawInit(BlitOpsT *ops, const DisplayT *d);</div>
<div class="func-body">
<p>Populate a BlitOpsT with the correct span functions for the display's pixel depth.
Must be called once after videoInit().</p>
<dl class="params">
<dt>ops</dt><dd>BlitOpsT to populate</dd>
<dt>d</dt><dd>Initialized display context</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void rectFill(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);</div>
<div class="func-body">
<p>Fill a rectangle with a solid color. Clips to the display clip rect. Workhorse for
backgrounds, window fills, and clear operations.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>x, y, w, h</dt><dd>Rectangle to fill</dd>
<dt>color</dt><dd>Packed pixel color</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void rectCopy(DisplayT *d, const BlitOpsT *ops, int32_t dstX, int32_t dstY, const uint8_t *srcBuf, int32_t srcPitch, int32_t srcX, int32_t srcY, int32_t w, int32_t h);</div>
<div class="func-body">
<p>Copy a rectangle from an arbitrary source buffer into the backbuffer. Used to blit
per-window content buffers during compositing.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>dstX, dstY</dt><dd>Destination position in backbuffer</dd>
<dt>srcBuf</dt><dd>Source pixel buffer</dd>
<dt>srcPitch</dt><dd>Source buffer bytes per row</dd>
<dt>srcX, srcY</dt><dd>Origin within source buffer</dd>
<dt>w, h</dt><dd>Rectangle dimensions to copy</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void rectCopyGrayscale(DisplayT *d, const BlitOpsT *ops, int32_t dstX, int32_t dstY, const uint8_t *srcBuf, int32_t srcPitch, int32_t srcX, int32_t srcY, int32_t w, int32_t h);</div>
<div class="func-body">
<p>Copy a rectangle with grayscale conversion. Each pixel's RGB is converted to luminance
(0.299R + 0.587G + 0.114B) for a disabled/grayed appearance.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>dstX, dstY</dt><dd>Destination position</dd>
<dt>srcBuf, srcPitch</dt><dd>Source buffer and pitch</dd>
<dt>srcX, srcY</dt><dd>Source origin</dd>
<dt>w, h</dt><dd>Rectangle dimensions</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void drawBevel(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, const BevelStyleT *style);</div>
<div class="func-body">
<p>Draw a beveled frame. Top/left edges in highlight color, bottom/right in shadow.
Interior filled with face color if non-zero.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>x, y, w, h</dt><dd>Outer bevel rectangle</dd>
<dt>style</dt><dd>Bevel colors and width</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t drawChar(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, char ch, uint32_t fg, uint32_t bg, bool opaque);</div>
<div class="func-body">
<p>Draw a single character glyph. When opaque is true, the background fills the entire cell;
when false, only foreground pixels are drawn (transparent background).</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>font</dt><dd>Bitmap font</dd>
<dt>x, y</dt><dd>Character position</dd>
<dt>ch</dt><dd>Character to draw</dd>
<dt>fg, bg</dt><dd>Foreground and background packed colors</dd>
<dt>opaque</dt><dd>true = fill background, false = transparent</dd>
</dl>
<p><span class="label">Returns:</span> Advance width (always charWidth)</p>
</div>
</div>
<div class="func">
<div class="func-sig">void drawText(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, uint32_t fg, uint32_t bg, bool opaque);</div>
<div class="func-body">
<p>Draw a null-terminated string. Calls drawChar per character.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>font</dt><dd>Bitmap font</dd>
<dt>x, y</dt><dd>Start position</dd>
<dt>text</dt><dd>Null-terminated string</dd>
<dt>fg, bg</dt><dd>Foreground and background packed colors</dd>
<dt>opaque</dt><dd>true = fill background, false = transparent</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void drawTextN(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, int32_t count, uint32_t fg, uint32_t bg, bool opaque);</div>
<div class="func-body">
<p>Optimized batch text rendering for a known character count. Computes clip bounds once,
fills background in a single rectFill, then overlays glyph foreground pixels. Significantly
faster than per-character drawChar for long runs (terminal rows, list items).</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>font</dt><dd>Bitmap font</dd>
<dt>x, y</dt><dd>Start position</dd>
<dt>text</dt><dd>Character buffer (not required to be null-terminated)</dd>
<dt>count</dt><dd>Number of characters to render</dd>
<dt>fg, bg</dt><dd>Foreground and background packed colors</dd>
<dt>opaque</dt><dd>true = fill background, false = transparent</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t textWidth(const BitmapFontT *font, const char *text);</div>
<div class="func-body">
<p>Return the pixel width of a null-terminated string (strlen(text) * charWidth).</p>
<dl class="params">
<dt>font</dt><dd>Bitmap font</dd>
<dt>text</dt><dd>Null-terminated string</dd>
</dl>
<p><span class="label">Returns:</span> Width in pixels</p>
</div>
</div>
<div class="func">
<div class="func-sig">char accelParse(const char *text);</div>
<div class="func-body">
<p>Scan text for an &amp; prefix and return the following character as a lowercase accelerator
key. "&amp;File" returns 'f', "E&amp;xit" returns 'x'.</p>
<dl class="params">
<dt>text</dt><dd>Text with optional &amp; accelerator marker</dd>
</dl>
<p><span class="label">Returns:</span> Lowercase accelerator character, or 0 if none</p>
</div>
</div>
<div class="func">
<div class="func-sig">void drawTextAccel(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, uint32_t fg, uint32_t bg, bool opaque);</div>
<div class="func-body">
<p>Draw text with &amp; accelerator markers. The character after &amp; is drawn underlined to
indicate the keyboard shortcut. &amp;&amp; produces a literal &amp;. Used for menu items and button labels.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>font</dt><dd>Bitmap font</dd>
<dt>x, y</dt><dd>Start position</dd>
<dt>text</dt><dd>Text with &amp; markers</dd>
<dt>fg, bg</dt><dd>Foreground and background packed colors</dd>
<dt>opaque</dt><dd>true = fill background, false = transparent</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t textWidthAccel(const BitmapFontT *font, const char *text);</div>
<div class="func-body">
<p>Measure text width excluding &amp; markers (so "&amp;File" measures as 4 chars).</p>
<dl class="params">
<dt>font</dt><dd>Bitmap font</dd>
<dt>text</dt><dd>Text with optional &amp; markers</dd>
</dl>
<p><span class="label">Returns:</span> Width in pixels</p>
</div>
</div>
<div class="func">
<div class="func-sig">void drawMaskedBitmap(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, const uint16_t *andMask, const uint16_t *xorData, uint32_t fgColor, uint32_t bgColor);</div>
<div class="func-body">
<p>Draw a 1-bit AND/XOR masked bitmap. Used for software-rendered mouse cursors.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>x, y</dt><dd>Screen position</dd>
<dt>w, h</dt><dd>Bitmap dimensions</dd>
<dt>andMask</dt><dd>AND transparency mask (one uint16_t per row)</dd>
<dt>xorData</dt><dd>XOR color data</dd>
<dt>fgColor, bgColor</dt><dd>Cursor foreground and background packed colors</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void drawTermRow(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, int32_t cols, const uint8_t *lineData, const uint32_t *palette, bool blinkVisible, int32_t cursorCol);</div>
<div class="func-body">
<p>Render an entire row of terminal character cells (ch/attr byte pairs) in a single pass.
Colors looked up from a 16-color palette. Attribute bit 7 controls blink.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>font</dt><dd>Bitmap font</dd>
<dt>x, y</dt><dd>Row start position</dd>
<dt>cols</dt><dd>Number of columns</dd>
<dt>lineData</dt><dd>Packed ch/attr byte pairs (2 bytes per cell)</dd>
<dt>palette</dt><dd>16-entry packed color palette</dd>
<dt>blinkVisible</dt><dd>false = hide blinking characters</dd>
<dt>cursorCol</dt><dd>Column for inverted text cursor (-1 = none)</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void drawFocusRect(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);</div>
<div class="func-body">
<p>Draw a 1px dotted rectangle (alternating pixels). Used for keyboard focus indicators,
matching the Windows 3.x focus rectangle convention.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>x, y, w, h</dt><dd>Focus rectangle bounds</dd>
<dt>color</dt><dd>Dot color (packed)</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void drawHLine(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, uint32_t color);</div>
<div class="func-body">
<p>Draw a horizontal line (1px tall).</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>x, y</dt><dd>Start position</dd>
<dt>w</dt><dd>Width in pixels</dd>
<dt>color</dt><dd>Packed pixel color</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void drawVLine(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t h, uint32_t color);</div>
<div class="func-body">
<p>Draw a vertical line (1px wide).</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>x, y</dt><dd>Start position</dd>
<dt>h</dt><dd>Height in pixels</dd>
<dt>color</dt><dd>Packed pixel color</dd>
</dl>
</div>
</div>
</div>
<!-- ============================================================ -->
<!-- dvxComp.h -->
<!-- ============================================================ -->
<div class="layer" id="comp">
<h2 class="layer-header">dvxComp.h -- Layer 3: Dirty Rectangle Compositor</h2>
<p class="layer-desc">
Tracks changed screen regions and ensures only dirty regions are redrawn and flushed
to video memory. The compositing pipeline: mark dirty, merge overlapping rects, redraw
desktop + windows (back-to-front, painter's algorithm), flush to LFB.
</p>
<div class="func">
<div class="func-sig">void dirtyListInit(DirtyListT *dl);</div>
<div class="func-body">
<p>Zero the dirty rect count. Called at the start of each frame.</p>
<dl class="params">
<dt>dl</dt><dd>Dirty list to initialize</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dirtyListAdd(DirtyListT *dl, int32_t x, int32_t y, int32_t w, int32_t h);</div>
<div class="func-body">
<p>Enqueue a dirty rectangle. Grows dynamically; triggers merge at a soft capacity limit.</p>
<dl class="params">
<dt>dl</dt><dd>Dirty list</dd>
<dt>x, y, w, h</dt><dd>Dirty rectangle in screen coordinates</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dirtyListMerge(DirtyListT *dl);</div>
<div class="func-body">
<p>Consolidate the dirty list by merging overlapping and adjacent rects. Uses iterative
pairwise merge: if combining two rects does not increase total area beyond a threshold,
they are merged. Reduces compositor passes and LFB flush operations.</p>
<dl class="params">
<dt>dl</dt><dd>Dirty list to merge</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dirtyListClear(DirtyListT *dl);</div>
<div class="func-body">
<p>Reset the dirty list to empty (sets count to 0).</p>
<dl class="params">
<dt>dl</dt><dd>Dirty list to clear</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void flushRect(DisplayT *d, const RectT *r);</div>
<div class="func-body">
<p>Copy a rectangle from the system RAM backbuffer to the LFB (video memory). This is
the only place the real framebuffer is written. Uses platform-specific fast copy
(rep movsd on DOS) for each scanline.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>r</dt><dd>Rectangle to flush</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">bool rectIntersect(const RectT *a, const RectT *b, RectT *result);</div>
<div class="func-body">
<p>Compute the intersection of two rectangles.</p>
<dl class="params">
<dt>a, b</dt><dd>Input rectangles</dd>
<dt>result</dt><dd>Output: intersection rectangle (valid only when return is true)</dd>
</dl>
<p><span class="label">Returns:</span> true if the rectangles overlap, false if disjoint</p>
</div>
</div>
<div class="func">
<div class="func-sig">bool rectIsEmpty(const RectT *r);</div>
<div class="func-body">
<p>Test whether a rectangle has zero or negative area.</p>
<dl class="params">
<dt>r</dt><dd>Rectangle to test</dd>
</dl>
<p><span class="label">Returns:</span> true if w &lt;= 0 or h &lt;= 0</p>
</div>
</div>
</div>
<!-- ============================================================ -->
<!-- dvxWm.h -->
<!-- ============================================================ -->
<div class="layer" id="wm">
<h2 class="layer-header">dvxWm.h -- Layer 4: Window Manager</h2>
<p class="layer-desc">
Manages the window lifecycle, Z-order stack, chrome drawing, hit testing, and
interactive operations (drag, resize, scroll). The WM owns window geometry and chrome;
content is owned by the application via callbacks or the widget system.
</p>
<h3>Initialization</h3>
<div class="func">
<div class="func-sig">void wmInit(WindowStackT *stack);</div>
<div class="func-body">
<p>Zero the window stack. Must be called before any other WM function.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack to initialize</dd>
</dl>
</div>
</div>
<h3>Window Lifecycle</h3>
<div class="func">
<div class="func-sig">WindowT *wmCreateWindow(WindowStackT *stack, DisplayT *d, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, bool resizable);</div>
<div class="func-body">
<p>Allocate a new window, initialize its geometry and content buffer, and push it to
the top of the Z-order stack. Returns with all callbacks NULL; the caller should set
onPaint/onKey/etc. before the next event loop iteration.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>d</dt><dd>Display context</dd>
<dt>title</dt><dd>Window title text</dd>
<dt>x, y</dt><dd>Initial position</dd>
<dt>w, h</dt><dd>Initial outer frame dimensions</dd>
<dt>resizable</dt><dd>true = allow user resize</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to new WindowT, or NULL on failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wmDestroyWindow(WindowStackT *stack, WindowT *win);</div>
<div class="func-body">
<p>Free the window's content buffer and all attached resources (menu bar, scrollbars,
widget tree), remove it from the stack, and dirty the vacated region.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>win</dt><dd>Window to destroy</dd>
</dl>
</div>
</div>
<h3>Z-Order and Focus</h3>
<div class="func">
<div class="func-sig">void wmRaiseWindow(WindowStackT *stack, DirtyListT *dl, int32_t idx);</div>
<div class="func-body">
<p>Move window at stack index idx to the top of the Z-order. Dirties both old and new
top positions so overlapping windows get repainted.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list for repaint marking</dd>
<dt>idx</dt><dd>Stack index of window to raise</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmSetFocus(WindowStackT *stack, DirtyListT *dl, int32_t idx);</div>
<div class="func-body">
<p>Transfer keyboard focus to the window at stack index idx. Unfocuses the previously
focused window and dirties both title bars.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>idx</dt><dd>Stack index of window to focus</dd>
</dl>
</div>
</div>
<h3>Geometry</h3>
<div class="func">
<div class="func-sig">void wmUpdateContentRect(WindowT *win);</div>
<div class="func-body">
<p>Recompute contentX/Y/W/H from the window's outer frame dimensions, accounting for
chrome borders, title bar, menu bar, and scrollbars. Must be called after any change
to frame size or chrome configuration.</p>
<dl class="params">
<dt>win</dt><dd>Window to update</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t wmReallocContentBuf(WindowT *win, const DisplayT *d);</div>
<div class="func-body">
<p>Reallocate the per-window content backbuffer to match current contentW/H. Old buffer
contents are lost; caller should trigger a full repaint via onPaint afterward.</p>
<dl class="params">
<dt>win</dt><dd>Window to reallocate</dd>
<dt>d</dt><dd>Display context (for bytes-per-pixel)</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, -1 on allocation failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wmMinWindowSize(const WindowT *win, int32_t *minW, int32_t *minH);</div>
<div class="func-body">
<p>Get the minimum window size. Accounts for chrome, gadgets, and menu bar.</p>
<dl class="params">
<dt>win</dt><dd>Window</dd>
<dt>minW, minH</dt><dd>Output: minimum width and height</dd>
</dl>
</div>
</div>
<h3>Menu Bar</h3>
<div class="func">
<div class="func-sig">MenuBarT *wmAddMenuBar(WindowT *win);</div>
<div class="func-body">
<p>Allocate and attach a menu bar to a window. Adjusts content area to make room
(CHROME_MENU_HEIGHT pixels). One menu bar per window.</p>
<dl class="params">
<dt>win</dt><dd>Window to add menu bar to</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the new MenuBarT</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wmDestroyMenuBar(WindowT *win);</div>
<div class="func-body">
<p>Free the menu bar and reclaim the content area.</p>
<dl class="params">
<dt>win</dt><dd>Window to remove menu bar from</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">MenuT *wmAddMenu(MenuBarT *bar, const char *label);</div>
<div class="func-body">
<p>Append a dropdown menu to the menu bar. The label supports &amp; accelerator markers
(e.g. "&amp;File").</p>
<dl class="params">
<dt>bar</dt><dd>Menu bar</dd>
<dt>label</dt><dd>Menu label text</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the new MenuT to populate with items</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wmAddMenuItem(MenuT *menu, const char *label, int32_t id);</div>
<div class="func-body">
<p>Append a clickable item to a menu. The id is passed to the window's onMenu callback
when selected.</p>
<dl class="params">
<dt>menu</dt><dd>Menu to append to</dd>
<dt>label</dt><dd>Item label (supports &amp; markers)</dd>
<dt>id</dt><dd>Application-defined command ID</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmAddMenuCheckItem(MenuT *menu, const char *label, int32_t id, bool checked);</div>
<div class="func-body">
<p>Add a checkbox-style menu item. Check state toggles on click; rendered with a checkmark glyph.</p>
<dl class="params">
<dt>menu</dt><dd>Menu to append to</dd>
<dt>label</dt><dd>Item label</dd>
<dt>id</dt><dd>Command ID</dd>
<dt>checked</dt><dd>Initial checked state</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmAddMenuRadioItem(MenuT *menu, const char *label, int32_t id, bool checked);</div>
<div class="func-body">
<p>Add a radio-style menu item. Radio groups are defined implicitly by consecutive radio
items; selecting one unchecks the others in the group.</p>
<dl class="params">
<dt>menu</dt><dd>Menu to append to</dd>
<dt>label</dt><dd>Item label</dd>
<dt>id</dt><dd>Command ID</dd>
<dt>checked</dt><dd>Initial checked state</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmAddMenuSeparator(MenuT *menu);</div>
<div class="func-body">
<p>Insert a horizontal separator line. Separators are not interactive.</p>
<dl class="params">
<dt>menu</dt><dd>Menu to append separator to</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">bool wmMenuItemIsChecked(MenuBarT *bar, int32_t id);</div>
<div class="func-body">
<p>Query the checked state of a menu item by command ID. Searches all menus in the bar.</p>
<dl class="params">
<dt>bar</dt><dd>Menu bar</dd>
<dt>id</dt><dd>Command ID to query</dd>
</dl>
<p><span class="label">Returns:</span> true if checked</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wmMenuItemSetChecked(MenuBarT *bar, int32_t id, bool checked);</div>
<div class="func-body">
<p>Set the checked state of a menu item by command ID. For radio items, setting
checked=true also unchecks other radio items in the same group.</p>
<dl class="params">
<dt>bar</dt><dd>Menu bar</dd>
<dt>id</dt><dd>Command ID</dd>
<dt>checked</dt><dd>New checked state</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmMenuItemSetEnabled(MenuBarT *bar, int32_t id, bool enabled);</div>
<div class="func-body">
<p>Enable or disable a menu item by command ID.</p>
<dl class="params">
<dt>bar</dt><dd>Menu bar</dd>
<dt>id</dt><dd>Command ID</dd>
<dt>enabled</dt><dd>true = enabled, false = grayed out</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">MenuT *wmAddSubMenu(MenuT *parentMenu, const char *label);</div>
<div class="func-body">
<p>Create a cascading submenu attached to a parent menu. The child MenuT is heap-allocated
and freed when the parent window is destroyed.</p>
<dl class="params">
<dt>parentMenu</dt><dd>Parent menu to attach submenu to</dd>
<dt>label</dt><dd>Submenu label text</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the child MenuT, or NULL on allocation failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">MenuT *wmCreateMenu(void);</div>
<div class="func-body">
<p>Allocate a heap-resident MenuT for use as a context menu (right-click). Unlike menu
bar menus, context menus are standalone allocations. Free with wmFreeMenu().</p>
<p><span class="label">Returns:</span> Pointer to the new MenuT</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wmFreeMenu(MenuT *menu);</div>
<div class="func-body">
<p>Free a standalone menu allocated with wmCreateMenu(). Also frees any heap-allocated
submenu children recursively.</p>
<dl class="params">
<dt>menu</dt><dd>Menu to free</dd>
</dl>
</div>
</div>
<h3>Scrollbars</h3>
<div class="func">
<div class="func-sig">ScrollbarT *wmAddVScrollbar(WindowT *win, int32_t min, int32_t max, int32_t pageSize);</div>
<div class="func-body">
<p>Attach a vertical scrollbar to the right edge of the window's content area. Shrinks
contentW by SCROLLBAR_WIDTH pixels.</p>
<dl class="params">
<dt>win</dt><dd>Window</dd>
<dt>min, max</dt><dd>Scroll value range</dd>
<dt>pageSize</dt><dd>Visible portion (controls thumb size)</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the new ScrollbarT</p>
</div>
</div>
<div class="func">
<div class="func-sig">ScrollbarT *wmAddHScrollbar(WindowT *win, int32_t min, int32_t max, int32_t pageSize);</div>
<div class="func-body">
<p>Attach a horizontal scrollbar to the bottom edge. Shrinks contentH by SCROLLBAR_WIDTH pixels.</p>
<dl class="params">
<dt>win</dt><dd>Window</dd>
<dt>min, max</dt><dd>Scroll value range</dd>
<dt>pageSize</dt><dd>Visible portion</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the new ScrollbarT</p>
</div>
</div>
<h3>Drawing</h3>
<div class="func">
<div class="func-sig">void wmDrawChrome(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors, WindowT *win, const RectT *clipTo);</div>
<div class="func-body">
<p>Draw the window frame: outer bevel, title bar with text, close/minimize/maximize
gadgets, and menu bar if present. Drawing is clipped to the intersection with clipTo.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>font</dt><dd>Bitmap font for title text</dd>
<dt>colors</dt><dd>Color scheme</dd>
<dt>win</dt><dd>Window to draw chrome for</dd>
<dt>clipTo</dt><dd>Dirty rectangle to clip drawing to</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmDrawContent(DisplayT *d, const BlitOpsT *ops, WindowT *win, const RectT *clipTo);</div>
<div class="func-body">
<p>Blit the window's content backbuffer into the display backbuffer, clipped to the
dirty rect. Pure copy operation (no drawing).</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>win</dt><dd>Window</dd>
<dt>clipTo</dt><dd>Dirty rectangle</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmDrawScrollbars(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, WindowT *win, const RectT *clipTo);</div>
<div class="func-body">
<p>Draw scrollbars (track, arrows, proportional thumb) for a window. Drawn after content
so scrollbars overlay the content area edge.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>colors</dt><dd>Color scheme</dd>
<dt>win</dt><dd>Window</dd>
<dt>clipTo</dt><dd>Dirty rectangle</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmDrawMinimizedIcons(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, const WindowStackT *stack, const RectT *clipTo);</div>
<div class="func-body">
<p>Draw icons for all minimized windows along the bottom of the screen. Each icon shows
a scaled preview of the window's content with a beveled border.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>colors</dt><dd>Color scheme</dd>
<dt>stack</dt><dd>Window stack</dd>
<dt>clipTo</dt><dd>Dirty rectangle</dd>
</dl>
</div>
</div>
<h3>Hit Testing</h3>
<div class="func">
<div class="func-sig">int32_t wmHitTest(const WindowStackT *stack, int32_t mx, int32_t my, int32_t *hitPart);</div>
<div class="func-body">
<p>Determine which window and chrome region is under the given screen coordinates.
Iterates front-to-back (highest Z first) so the topmost window wins.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>mx, my</dt><dd>Screen coordinates</dd>
<dt>hitPart</dt><dd>Output: HIT_CONTENT, HIT_TITLE, HIT_CLOSE, HIT_RESIZE, HIT_MENU, HIT_VSCROLL, HIT_HSCROLL, HIT_MINIMIZE, HIT_MAXIMIZE</dd>
</dl>
<p><span class="label">Returns:</span> Stack index of hit window, or -1 for desktop</p>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t wmResizeEdgeHit(const WindowT *win, int32_t mx, int32_t my);</div>
<div class="func-body">
<p>Determine which edge(s) of a window's border zone are targeted for resize.</p>
<dl class="params">
<dt>win</dt><dd>Window</dd>
<dt>mx, my</dt><dd>Screen coordinates</dd>
</dl>
<p><span class="label">Returns:</span> Bitmask of RESIZE_LEFT / RESIZE_RIGHT / RESIZE_TOP / RESIZE_BOTTOM</p>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t wmMinimizedIconHit(const WindowStackT *stack, const DisplayT *d, int32_t mx, int32_t my);</div>
<div class="func-body">
<p>Hit-test minimized icons at the bottom of the screen.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>d</dt><dd>Display context</dd>
<dt>mx, my</dt><dd>Screen coordinates</dd>
</dl>
<p><span class="label">Returns:</span> Stack index of the minimized window, or -1</p>
</div>
</div>
<h3>Drag and Resize</h3>
<div class="func">
<div class="func-sig">void wmDragBegin(WindowStackT *stack, int32_t idx, int32_t mouseX, int32_t mouseY);</div>
<div class="func-body">
<p>Begin a window drag operation. Records the mouse offset from the window origin.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>idx</dt><dd>Stack index of window to drag</dd>
<dt>mouseX, mouseY</dt><dd>Current mouse position</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmDragMove(WindowStackT *stack, DirtyListT *dl, int32_t mouseX, int32_t mouseY, int32_t screenW, int32_t screenH);</div>
<div class="func-body">
<p>Update window position during an active drag. Dirties both old and new positions.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>mouseX, mouseY</dt><dd>Current mouse position</dd>
<dt>screenW, screenH</dt><dd>Screen dimensions (for clamping)</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmDragEnd(WindowStackT *stack);</div>
<div class="func-body">
<p>End the current drag operation. Clears dragWindow state.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmResizeBegin(WindowStackT *stack, int32_t idx, int32_t edge, int32_t mouseX, int32_t mouseY);</div>
<div class="func-body">
<p>Begin a window resize operation. Records which edge(s) are being dragged.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>idx</dt><dd>Stack index</dd>
<dt>edge</dt><dd>Bitmask of RESIZE_xxx flags</dd>
<dt>mouseX, mouseY</dt><dd>Current mouse position</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_t *mouseX, int32_t *mouseY);</div>
<div class="func-body">
<p>Update window dimensions during an active resize. Enforces MIN_WINDOW_W/H and
maxW/maxH constraints. Reallocates content buffer and calls onResize if size changed.
mouseX/mouseY are in/out: clamped on return for cursor warping.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>d</dt><dd>Display context</dd>
<dt>mouseX, mouseY</dt><dd>In/out: mouse position (clamped on return)</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmResizeEnd(WindowStackT *stack);</div>
<div class="func-body">
<p>End the current resize operation. Clears resizeWindow state.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
</dl>
</div>
</div>
<h3>Scrollbar Interaction</h3>
<div class="func">
<div class="func-sig">void wmScrollbarClick(WindowStackT *stack, DirtyListT *dl, int32_t idx, int32_t orient, int32_t mx, int32_t my);</div>
<div class="func-body">
<p>Handle an initial click on a scrollbar. Determines what was hit (arrows, trough, or
thumb) and either adjusts the value immediately or begins a thumb drag.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>idx</dt><dd>Stack index of window</dd>
<dt>orient</dt><dd>SCROLL_VERTICAL or SCROLL_HORIZONTAL</dd>
<dt>mx, my</dt><dd>Click screen coordinates</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmScrollbarDrag(WindowStackT *stack, DirtyListT *dl, int32_t mx, int32_t my);</div>
<div class="func-body">
<p>Update the scroll value during an active thumb drag. Maps mouse position along the
track to a proportional scroll value.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>mx, my</dt><dd>Current mouse position</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmScrollbarEnd(WindowStackT *stack);</div>
<div class="func-body">
<p>End an active scrollbar thumb drag.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
</dl>
</div>
</div>
<h3>Minimize / Maximize / Restore</h3>
<div class="func">
<div class="func-sig">void wmMaximize(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, WindowT *win);</div>
<div class="func-body">
<p>Maximize a window. Saves current geometry, then expands to screen or maxW/maxH bounds.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>d</dt><dd>Display context</dd>
<dt>win</dt><dd>Window to maximize</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmMinimize(WindowStackT *stack, DirtyListT *dl, WindowT *win);</div>
<div class="func-body">
<p>Minimize a window. Hides the window and shows an icon at the bottom of the screen.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>win</dt><dd>Window to minimize</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmRestore(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, WindowT *win);</div>
<div class="func-body">
<p>Restore a maximized window to its pre-maximize geometry.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>d</dt><dd>Display context</dd>
<dt>win</dt><dd>Maximized window to restore</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmRestoreMinimized(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, WindowT *win);</div>
<div class="func-body">
<p>Restore a minimized window (show it again and remove the icon).</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>d</dt><dd>Display context</dd>
<dt>win</dt><dd>Minimized window to restore</dd>
</dl>
</div>
</div>
<h3>Minimized Icon Layout</h3>
<div class="func">
<div class="func-sig">void wmMinimizedIconPos(const DisplayT *d, int32_t index, int32_t *x, int32_t *y);</div>
<div class="func-body">
<p>Compute the screen position of a minimized icon by ordinal index. Icons wrap into
rows from bottom to top when the screen fills up.</p>
<dl class="params">
<dt>d</dt><dd>Display context</dd>
<dt>index</dt><dd>Ordinal index of the minimized icon</dd>
<dt>x, y</dt><dd>Output: screen position</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wmMinimizedIconRect(const WindowStackT *stack, const DisplayT *d, int32_t *y, int32_t *h);</div>
<div class="func-body">
<p>Compute the screen rect covering all minimized icon rows. Used to dirty the icon area
when windows are minimized or restored.</p>
<dl class="params">
<dt>stack</dt><dd>Window stack</dd>
<dt>d</dt><dd>Display context</dd>
<dt>y, h</dt><dd>Output: vertical extent of icon area</dd>
</dl>
</div>
</div>
<h3>Miscellaneous</h3>
<div class="func">
<div class="func-sig">void wmSetTitle(WindowT *win, DirtyListT *dl, const char *title);</div>
<div class="func-body">
<p>Set the window title and dirty the title bar for repaint.</p>
<dl class="params">
<dt>win</dt><dd>Window</dd>
<dt>dl</dt><dd>Dirty list</dd>
<dt>title</dt><dd>New title text</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t wmSetIcon(WindowT *win, const char *path, const DisplayT *d);</div>
<div class="func-body">
<p>Load an icon image for a window from a file. Converts to display pixel format.</p>
<dl class="params">
<dt>win</dt><dd>Window</dd>
<dt>path</dt><dd>Image file path</dd>
<dt>d</dt><dd>Display context</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, -1 on failure</p>
</div>
</div>
</div>
<!-- ============================================================ -->
<!-- dvxApp.h -->
<!-- ============================================================ -->
<div class="layer" id="app">
<h2 class="layer-header">dvxApp.h -- Layer 5: Application API</h2>
<p class="layer-desc">
The topmost layer and the public-facing API. Aggregates all lower layers into a single
AppContextT. Applications interact exclusively through dvx*() functions and window
callbacks. The event loop follows a cooperative model: poll, dispatch, composite, yield.
</p>
<h3>AppContextT</h3>
<div class="type-section">
<div class="type-header">AppContextT</div>
<div class="type-body">
Single monolithic context that owns all GUI state. Contains the display, window stack,
dirty list, blit ops, font, color scheme, popup state, cursor state, mouse/keyboard state,
tooltip state, wallpaper buffer, video mode list, and various configuration fields.
Allocated on the caller's stack or statically.
</div>
</div>
<h3>Initialization and Shutdown</h3>
<div class="func">
<div class="func-sig">int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);</div>
<div class="func-body">
<p>Initialize the entire GUI stack: video mode, input devices, font, color scheme, cursor
shapes, and internal state. Single entry point for starting a DVX application.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context to initialize</dd>
<dt>requestedW, requestedH</dt><dd>Desired screen resolution</dd>
<dt>preferredBpp</dt><dd>Preferred bits per pixel</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, negative on failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxShutdown(AppContextT *ctx);</div>
<div class="func-body">
<p>Tear down the GUI stack in reverse order: destroy all windows, restore text mode,
release input devices. Safe to call after a failed dvxInit().</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t dvxChangeVideoMode(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);</div>
<div class="func-body">
<p>Switch to a new video mode live. Reallocates the backbuffer, all window content buffers,
repacks colors, rescales wallpaper, and repositions off-screen windows.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>requestedW, requestedH</dt><dd>New resolution</dd>
<dt>preferredBpp</dt><dd>New bits per pixel</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, -1 on failure (old mode restored)</p>
</div>
</div>
<h3>Event Loop</h3>
<div class="func">
<div class="func-sig">void dvxRun(AppContextT *ctx);</div>
<div class="func-body">
<p>Enter the main event loop. Polls input, dispatches events, composites dirty regions,
and yields on each iteration. Returns when ctx->running becomes false.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">bool dvxUpdate(AppContextT *ctx);</div>
<div class="func-body">
<p>Process exactly one frame of the event loop. For applications that integrate the GUI
into their own main loop (e.g. polling serial ports between frames).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
<p><span class="label">Returns:</span> false when the GUI wants to exit</p>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxQuit(AppContextT *ctx);</div>
<div class="func-body">
<p>Request exit from the main event loop (sets ctx->running = false).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<h3>Window Management</h3>
<div class="func">
<div class="func-sig">WindowT *dvxCreateWindow(AppContextT *ctx, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, bool resizable);</div>
<div class="func-body">
<p>Create a window at an explicit screen position. The window is raised to the top,
focused, and its entire region is dirtied.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>title</dt><dd>Window title</dd>
<dt>x, y</dt><dd>Screen position</dd>
<dt>w, h</dt><dd>Outer frame dimensions</dd>
<dt>resizable</dt><dd>true = allow user resize</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to new WindowT</p>
</div>
</div>
<div class="func">
<div class="func-sig">WindowT *dvxCreateWindowCentered(AppContextT *ctx, const char *title, int32_t w, int32_t h, bool resizable);</div>
<div class="func-body">
<p>Convenience wrapper that centers the window on screen.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>title</dt><dd>Window title</dd>
<dt>w, h</dt><dd>Outer frame dimensions</dd>
<dt>resizable</dt><dd>true = allow user resize</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to new WindowT</p>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxDestroyWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Destroy a window, free all its resources, and dirty its former region.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to destroy</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxRaiseWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Raise a window to the top of the Z-order and give it focus.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to raise</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxFitWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Resize a window to exactly fit its widget tree's computed minimum size (plus chrome).
Used for dialog boxes and fixed-layout windows.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to fit</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxFitWindowW(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Resize window width only to fit widget tree's minimum width (plus chrome).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to fit</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxFitWindowH(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Resize window height only to fit widget tree's minimum height (plus chrome).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to fit</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxResizeWindow(AppContextT *ctx, WindowT *win, int32_t newW, int32_t newH);</div>
<div class="func-body">
<p>Programmatically resize a window to the specified outer dimensions.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to resize</dd>
<dt>newW, newH</dt><dd>New outer frame dimensions</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxMinimizeWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Minimize a window (show as icon at bottom of screen).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to minimize</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxMaximizeWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Maximize a window (expand to fill screen or maxW/maxH).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to maximize</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxHideWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Hide a window without destroying it. Marks the exposed region dirty.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to hide</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxShowWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Show a previously hidden window. Marks its region dirty for repaint.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to show</dd>
</dl>
</div>
</div>
<h3>Invalidation</h3>
<div class="func">
<div class="func-sig">void dvxInvalidateRect(AppContextT *ctx, WindowT *win, int32_t x, int32_t y, int32_t w, int32_t h);</div>
<div class="func-body">
<p>Mark a sub-region of a window's content area as needing repaint. Coordinates are
relative to the content area, not the screen. Triggers onPaint during the next
composite pass.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window</dd>
<dt>x, y, w, h</dt><dd>Dirty rectangle in content-relative coordinates</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxInvalidateWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Mark the entire window content area as dirty.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to invalidate</dd>
</dl>
</div>
</div>
<h3>Window Properties</h3>
<div class="func">
<div class="func-sig">void dvxSetTitle(AppContextT *ctx, WindowT *win, const char *title);</div>
<div class="func-body">
<p>Set a window's title text and dirty the title bar.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window</dd>
<dt>title</dt><dd>New title text</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t dvxSetWindowIcon(AppContextT *ctx, WindowT *win, const char *path);</div>
<div class="func-body">
<p>Load an icon for a window from an image file.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window</dd>
<dt>path</dt><dd>Image file path</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, -1 on failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxSetBusy(AppContextT *ctx, bool busy);</div>
<div class="func-body">
<p>Set or clear busy state. While busy, the hourglass cursor is shown and input is blocked.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>busy</dt><dd>true = show hourglass, false = normal</dd>
</dl>
</div>
</div>
<h3>Accessors</h3>
<div class="func">
<div class="func-sig">const BitmapFontT *dvxGetFont(const AppContextT *ctx);</div>
<div class="func-body">
<p>Get a pointer to the default font.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the active BitmapFontT</p>
</div>
</div>
<div class="func">
<div class="func-sig">const ColorSchemeT *dvxGetColors(const AppContextT *ctx);</div>
<div class="func-body">
<p>Get a pointer to the current color scheme.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the active ColorSchemeT</p>
</div>
</div>
<div class="func">
<div class="func-sig">DisplayT *dvxGetDisplay(AppContextT *ctx);</div>
<div class="func-body">
<p>Get a pointer to the display context.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the DisplayT</p>
</div>
</div>
<div class="func">
<div class="func-sig">const BlitOpsT *dvxGetBlitOps(const AppContextT *ctx);</div>
<div class="func-body">
<p>Get a pointer to the blit operations vtable.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the active BlitOpsT</p>
</div>
</div>
<div class="func">
<div class="func-sig">const VideoModeInfoT *dvxGetVideoModes(const AppContextT *ctx, int32_t *count);</div>
<div class="func-body">
<p>Return the list of available video modes enumerated at init time.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>count</dt><dd>Output: number of mode entries</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the VideoModeInfoT array</p>
</div>
</div>
<h3>Color Scheme</h3>
<div class="func">
<div class="func-sig">void dvxSetColor(AppContextT *ctx, ColorIdE id, uint8_t r, uint8_t g, uint8_t b);</div>
<div class="func-body">
<p>Set a single color by ID. Repacks to native pixel format and invalidates the entire screen.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>id</dt><dd>Color ID (ColorIdE)</dd>
<dt>r, g, b</dt><dd>RGB values (0-255)</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxGetColor(const AppContextT *ctx, ColorIdE id, uint8_t *r, uint8_t *g, uint8_t *b);</div>
<div class="func-body">
<p>Get a color's RGB values by ID.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>id</dt><dd>Color ID (ColorIdE)</dd>
<dt>r, g, b</dt><dd>Output: RGB values</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxApplyColorScheme(AppContextT *ctx);</div>
<div class="func-body">
<p>Apply all colors from ctx->colorRgb[] at once (repack + full repaint).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxResetColorScheme(AppContextT *ctx);</div>
<div class="func-body">
<p>Reset all colors to the built-in defaults and repaint.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">bool dvxLoadTheme(AppContextT *ctx, const char *filename);</div>
<div class="func-body">
<p>Load a theme file (INI format with [colors] section) and apply it.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>filename</dt><dd>Path to theme INI file</dd>
</dl>
<p><span class="label">Returns:</span> true on success</p>
</div>
</div>
<div class="func">
<div class="func-sig">bool dvxSaveTheme(const AppContextT *ctx, const char *filename);</div>
<div class="func-body">
<p>Save the current color scheme to a theme file.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>filename</dt><dd>Output file path</dd>
</dl>
<p><span class="label">Returns:</span> true on success</p>
</div>
</div>
<div class="func">
<div class="func-sig">const char *dvxColorName(ColorIdE id);</div>
<div class="func-body">
<p>Return the INI key name for a color ID (e.g. "desktop", "windowFace").</p>
<dl class="params">
<dt>id</dt><dd>Color ID</dd>
</dl>
<p><span class="label">Returns:</span> Static string</p>
</div>
</div>
<div class="func">
<div class="func-sig">const char *dvxColorLabel(ColorIdE id);</div>
<div class="func-body">
<p>Return a human-readable display label (e.g. "Desktop", "Cursor Color").</p>
<dl class="params">
<dt>id</dt><dd>Color ID</dd>
</dl>
<p><span class="label">Returns:</span> Static string</p>
</div>
</div>
<h3>Wallpaper</h3>
<div class="func">
<div class="func-sig">bool dvxSetWallpaper(AppContextT *ctx, const char *path);</div>
<div class="func-body">
<p>Load and apply a wallpaper image using the current wallpaperMode (stretch/tile/center).
Pass NULL to clear the wallpaper.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>path</dt><dd>Image file path, or NULL to clear</dd>
</dl>
<p><span class="label">Returns:</span> true on success</p>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxSetWallpaperMode(AppContextT *ctx, WallpaperModeE mode);</div>
<div class="func-body">
<p>Change the wallpaper display mode and re-render. No effect if no wallpaper is loaded.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>mode</dt><dd>WallpaperStretchE, WallpaperTileE, or WallpaperCenterE</dd>
</dl>
</div>
</div>
<h3>Mouse Configuration</h3>
<div class="func">
<div class="func-sig">void dvxSetMouseConfig(AppContextT *ctx, int32_t wheelDir, int32_t dblClickMs, int32_t accelThreshold);</div>
<div class="func-body">
<p>Configure mouse behavior.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>wheelDir</dt><dd>1 = normal, -1 = reversed</dd>
<dt>dblClickMs</dt><dd>Double-click speed in milliseconds (e.g. 500)</dd>
<dt>accelThreshold</dt><dd>Double-speed threshold in mickeys/sec (0 = don't change)</dd>
</dl>
</div>
</div>
<h3>Accelerators</h3>
<div class="func">
<div class="func-sig">AccelTableT *dvxCreateAccelTable(void);</div>
<div class="func-body">
<p>Allocate a new accelerator table. Attach to a window via win->accelTable.</p>
<p><span class="label">Returns:</span> Pointer to new AccelTableT</p>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxFreeAccelTable(AccelTableT *table);</div>
<div class="func-body">
<p>Free an accelerator table and its entries.</p>
<dl class="params">
<dt>table</dt><dd>Table to free</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxAddAccel(AccelTableT *table, int32_t key, int32_t modifiers, int32_t cmdId);</div>
<div class="func-body">
<p>Register a keyboard shortcut. On match, fires the window's onMenu callback with cmdId.</p>
<dl class="params">
<dt>table</dt><dd>Accelerator table</dd>
<dt>key</dt><dd>ASCII character or KEY_Fxx constant</dd>
<dt>modifiers</dt><dd>Bitmask of ACCEL_CTRL / ACCEL_SHIFT / ACCEL_ALT</dd>
<dt>cmdId</dt><dd>Command ID passed to onMenu</dd>
</dl>
</div>
</div>
<h3>Window Arrangement</h3>
<div class="func">
<div class="func-sig">void dvxCascadeWindows(AppContextT *ctx);</div>
<div class="func-body">
<p>Cascade all visible, non-minimized windows. Each is offset diagonally by the title bar height.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxTileWindows(AppContextT *ctx);</div>
<div class="func-body">
<p>Arrange visible windows in an NxM grid filling the screen.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxTileWindowsH(AppContextT *ctx);</div>
<div class="func-body">
<p>Tile windows horizontally (side by side, equal width, full height).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxTileWindowsV(AppContextT *ctx);</div>
<div class="func-body">
<p>Tile windows vertically (stacked, full width, equal height).</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
</dl>
</div>
</div>
<h3>Image I/O</h3>
<div class="func">
<div class="func-sig">uint8_t *dvxLoadImage(const AppContextT *ctx, const char *path, int32_t *outW, int32_t *outH, int32_t *outPitch);</div>
<div class="func-body">
<p>Load an image file (BMP, PNG, JPEG, GIF) and convert to the display's native pixel
format. Caller must free with dvxFreeImage().</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>path</dt><dd>Image file path</dd>
<dt>outW, outH</dt><dd>Output: image dimensions</dd>
<dt>outPitch</dt><dd>Output: row pitch in bytes</dd>
</dl>
<p><span class="label">Returns:</span> Pixel buffer, or NULL on failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">uint8_t *dvxLoadImageFromMemory(const AppContextT *ctx, const uint8_t *data, int32_t dataLen, int32_t *outW, int32_t *outH, int32_t *outPitch);</div>
<div class="func-body">
<p>Load an image from a memory buffer. Same output format as dvxLoadImage(). Caller must
free with dvxFreeImage().</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>data</dt><dd>Image data buffer</dd>
<dt>dataLen</dt><dd>Buffer size in bytes</dd>
<dt>outW, outH</dt><dd>Output: image dimensions</dd>
<dt>outPitch</dt><dd>Output: row pitch in bytes</dd>
</dl>
<p><span class="label">Returns:</span> Pixel buffer, or NULL on failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">void dvxFreeImage(uint8_t *data);</div>
<div class="func-body">
<p>Free a pixel buffer returned by dvxLoadImage() or dvxLoadImageFromMemory().</p>
<dl class="params">
<dt>data</dt><dd>Buffer to free</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">bool dvxImageInfo(const char *path, int32_t *outW, int32_t *outH);</div>
<div class="func-body">
<p>Query image dimensions without decoding the full file.</p>
<dl class="params">
<dt>path</dt><dd>Image file path</dd>
<dt>outW, outH</dt><dd>Output: image dimensions</dd>
</dl>
<p><span class="label">Returns:</span> true on success</p>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t dvxSaveImage(const AppContextT *ctx, const uint8_t *data, int32_t w, int32_t h, int32_t pitch, const char *path);</div>
<div class="func-body">
<p>Save native-format pixel data to a PNG file.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>data</dt><dd>Pixel data in display native format</dd>
<dt>w, h</dt><dd>Image dimensions</dd>
<dt>pitch</dt><dd>Row pitch in bytes</dd>
<dt>path</dt><dd>Output file path</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, -1 on failure</p>
</div>
</div>
<h3>Screenshots</h3>
<div class="func">
<div class="func-sig">int32_t dvxScreenshot(AppContextT *ctx, const char *path);</div>
<div class="func-body">
<p>Save the entire screen (backbuffer contents) to a PNG file. Converts from native
pixel format to RGB.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>path</dt><dd>Output PNG file path</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, -1 on failure</p>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t dvxWindowScreenshot(AppContextT *ctx, WindowT *win, const char *path);</div>
<div class="func-body">
<p>Save a window's content to a PNG file.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window</dd>
<dt>path</dt><dd>Output PNG file path</dd>
</dl>
<p><span class="label">Returns:</span> 0 on success, -1 on failure</p>
</div>
</div>
<h3>Clipboard</h3>
<div class="func">
<div class="func-sig">void dvxClipboardCopy(const char *text, int32_t len);</div>
<div class="func-body">
<p>Copy text to the process-wide clipboard buffer. Simple static buffer (not inter-process).</p>
<dl class="params">
<dt>text</dt><dd>Text to copy</dd>
<dt>len</dt><dd>Length in bytes</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">const char *dvxClipboardGet(int32_t *outLen);</div>
<div class="func-body">
<p>Retrieve the current clipboard contents. Returns a pointer to the internal buffer
(valid until the next dvxClipboardCopy), or NULL if empty.</p>
<dl class="params">
<dt>outLen</dt><dd>Output: length of clipboard text</dd>
</dl>
<p><span class="label">Returns:</span> Clipboard text, or NULL</p>
</div>
</div>
<h3>Resource Loading</h3>
<div class="func">
<div class="func-sig">uint8_t *dvxResLoadIcon(AppContextT *ctx, const char *dxePath, const char *resName, int32_t *outW, int32_t *outH, int32_t *outPitch);</div>
<div class="func-body">
<p>Load an icon/image resource from a DXE file and decode to native pixel format.
Caller must free with dvxFreeImage().</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>dxePath</dt><dd>Path to DXE file</dd>
<dt>resName</dt><dd>Resource name within the DXE</dd>
<dt>outW, outH</dt><dd>Output: image dimensions</dd>
<dt>outPitch</dt><dd>Output: row pitch</dd>
</dl>
<p><span class="label">Returns:</span> Pixel buffer, or NULL if not found</p>
</div>
</div>
<div class="func">
<div class="func-sig">bool dvxResLoadText(const char *dxePath, const char *resName, char *buf, int32_t bufSize);</div>
<div class="func-body">
<p>Load a text resource from a DXE file into a caller-provided buffer. Null-terminated
and truncated to fit bufSize.</p>
<dl class="params">
<dt>dxePath</dt><dd>Path to DXE file</dd>
<dt>resName</dt><dd>Resource name</dd>
<dt>buf</dt><dd>Output buffer</dd>
<dt>bufSize</dt><dd>Buffer capacity</dd>
</dl>
<p><span class="label">Returns:</span> true on success</p>
</div>
</div>
<div class="func">
<div class="func-sig">void *dvxResLoadData(const char *dxePath, const char *resName, uint32_t *outSize);</div>
<div class="func-body">
<p>Load a raw binary resource from a DXE file. Returns a malloc'd buffer that the
caller must free.</p>
<dl class="params">
<dt>dxePath</dt><dd>Path to DXE file</dd>
<dt>resName</dt><dd>Resource name</dd>
<dt>outSize</dt><dd>Output: data size in bytes</dd>
</dl>
<p><span class="label">Returns:</span> Data buffer, or NULL if not found</p>
</div>
</div>
<h3>Utilities</h3>
<div class="func">
<div class="func-sig">uint32_t dvxTextHash(const char *text);</div>
<div class="func-body">
<p>Compute a djb2-xor hash for cheap dirty detection. Compare at save time with
the current hash to detect changes without a shadow copy. Not cryptographic.</p>
<dl class="params">
<dt>text</dt><dd>Null-terminated string to hash</dd>
</dl>
<p><span class="label">Returns:</span> 32-bit hash value</p>
</div>
</div>
</div>
<!-- ============================================================ -->
<!-- dvxWidget.h -->
<!-- ============================================================ -->
<div class="layer" id="widget">
<h2 class="layer-header">dvxWidget.h -- Widget System</h2>
<p class="layer-desc">
Retained-mode widget toolkit layered on the DVX window manager. Widgets form a tree
(parent-child) rooted at a per-window VBox container. Layout is automatic: measure
minimum sizes bottom-up, then allocate space top-down with flexbox-like weighted
distribution. Widget types are registered dynamically at runtime via DXE plugins.
</p>
<h3>WidgetT Structure</h3>
<div class="type-section">
<div class="type-header">WidgetT</div>
<div class="type-body">
Core widget structure. Generic across all widget types; type-specific data lives in
the void *data pointer managed by each widget's DXE.
<dl class="params">
<dt>int32_t type</dt><dd>Widget type ID (assigned by wgtRegisterClass)</dd>
<dt>const WidgetClassT *wclass</dt><dd>Vtable for this widget type</dd>
<dt>char name[MAX_WIDGET_NAME]</dt><dd>Widget name for lookup via wgtFind</dd>
<dt>parent, firstChild, lastChild, nextSibling</dt><dd>Tree linkage pointers</dd>
<dt>WindowT *window</dt><dd>Owning window</dd>
<dt>int32_t x, y, w, h</dt><dd>Computed geometry (relative to window content area)</dd>
<dt>int32_t calcMinW, calcMinH</dt><dd>Computed minimum size (from layout pass)</dd>
<dt>int32_t minW, minH, maxW, maxH, prefW, prefH</dt><dd>Size hints (tagged: wgtPixels/wgtChars/wgtPercent)</dd>
<dt>int32_t weight</dt><dd>Extra-space distribution weight (0 = fixed, 100 = normal)</dd>
<dt>WidgetAlignE align</dt><dd>Main-axis alignment for children</dd>
<dt>int32_t spacing, padding</dt><dd>Tagged sizes for child spacing and internal padding</dd>
<dt>uint32_t fgColor, bgColor</dt><dd>Custom colors (0 = use scheme defaults)</dd>
<dt>bool visible, enabled, readOnly</dt><dd>State flags</dd>
<dt>bool swallowTab</dt><dd>Tab key goes to widget, not focus navigation</dd>
<dt>char accelKey</dt><dd>Accelerator character (0 = none)</dd>
<dt>void *userData, *data</dt><dd>Application data and widget-private data</dd>
<dt>const char *tooltip</dt><dd>Tooltip text (NULL = none)</dd>
<dt>MenuT *contextMenu</dt><dd>Right-click menu (NULL = none)</dd>
</dl>
<p><span class="label">Universal Callbacks:</span></p>
<dl class="params">
<dt>onClick(WidgetT *w)</dt><dd>Widget clicked</dd>
<dt>onDblClick(WidgetT *w)</dt><dd>Widget double-clicked</dd>
<dt>onChange(WidgetT *w)</dt><dd>Value changed</dd>
<dt>onFocus(WidgetT *w)</dt><dd>Widget gained focus</dd>
<dt>onBlur(WidgetT *w)</dt><dd>Widget lost focus</dd>
<dt>onKeyPress(WidgetT *w, int32_t keyAscii)</dt><dd>ASCII key press</dd>
<dt>onKeyDown(WidgetT *w, int32_t keyCode, int32_t shift)</dt><dd>Key down</dd>
<dt>onKeyUp(WidgetT *w, int32_t keyCode, int32_t shift)</dt><dd>Key up</dd>
<dt>onMouseDown(WidgetT *w, int32_t button, int32_t x, int32_t y)</dt><dd>Mouse button pressed</dd>
<dt>onMouseUp(WidgetT *w, int32_t button, int32_t x, int32_t y)</dt><dd>Mouse button released</dd>
<dt>onMouseMove(WidgetT *w, int32_t button, int32_t x, int32_t y)</dt><dd>Mouse moved</dd>
<dt>onScroll(WidgetT *w, int32_t delta)</dt><dd>Mouse wheel</dd>
<dt>onValidate(WidgetT *w)</dt><dd>Return false to cancel a write</dd>
</dl>
</div>
</div>
<h3>Size Specification Macros</h3>
<table class="define-table">
<tr><th>Macro</th><th>Description</th></tr>
<tr><td>wgtPixels(v)</td><td>Size in pixels</td></tr>
<tr><td>wgtChars(v)</td><td>Size in character widths (multiplied by charWidth at layout time)</td></tr>
<tr><td>wgtPercent(v)</td><td>Size as percentage of parent dimension</td></tr>
</table>
<h3>Widget Class Flags</h3>
<table class="define-table">
<tr><th>Flag</th><th>Description</th></tr>
<tr><td>WCLASS_FOCUSABLE</td><td>Can receive keyboard focus (Tab navigation)</td></tr>
<tr><td>WCLASS_HORIZ_CONTAINER</td><td>Lays out children horizontally (vs. vertical)</td></tr>
<tr><td>WCLASS_PAINTS_CHILDREN</td><td>Widget handles child rendering itself</td></tr>
<tr><td>WCLASS_NO_HIT_RECURSE</td><td>Hit testing stops here, no child recursion</td></tr>
<tr><td>WCLASS_FOCUS_FORWARD</td><td>Accel hit forwards focus to next focusable sibling</td></tr>
<tr><td>WCLASS_HAS_POPUP</td><td>Has dropdown popup overlay</td></tr>
<tr><td>WCLASS_SCROLLABLE</td><td>Accepts mouse wheel events</td></tr>
<tr><td>WCLASS_SCROLL_CONTAINER</td><td>Scroll container (ScrollPane)</td></tr>
<tr><td>WCLASS_NEEDS_POLL</td><td>Needs periodic polling</td></tr>
<tr><td>WCLASS_SWALLOWS_TAB</td><td>Tab key goes to widget, not focus navigation</td></tr>
<tr><td>WCLASS_RELAYOUT_ON_SCROLL</td><td>Full relayout on scrollbar drag</td></tr>
<tr><td>WCLASS_PRESS_RELEASE</td><td>Click = press + release (Button, ImageButton)</td></tr>
<tr><td>WCLASS_ACCEL_WHEN_HIDDEN</td><td>Accelerator matching works even when invisible</td></tr>
</table>
<h3>Window Integration</h3>
<div class="func">
<div class="func-sig">WidgetT *wgtInitWindow(AppContextT *ctx, WindowT *win);</div>
<div class="func-body">
<p>Initialize the widget system for a window. Creates a root VBox container that fills
the content area, and installs callback handlers (onPaint, onMouse, onKey, onResize)
for widget-based event dispatch. The window's userData is set to the AppContextT pointer.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>win</dt><dd>Window to initialize</dd>
</dl>
<p><span class="label">Returns:</span> Root VBox widget (add children to this)</p>
</div>
</div>
<h3>Widget Operations</h3>
<div class="func">
<div class="func-sig">AppContextT *wgtGetContext(const WidgetT *w);</div>
<div class="func-body">
<p>Walk from any widget up the tree to the root, then retrieve the AppContextT stored
in the window's userData. Lets any widget access the full application context.</p>
<dl class="params">
<dt>w</dt><dd>Any widget in the tree</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the AppContextT</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtInvalidate(WidgetT *w);</div>
<div class="func-body">
<p>Mark a widget as needing both re-layout (measure + position) and repaint. Propagates
upward to ancestors. Use after structural changes (adding/removing children, text changes
that affect size).</p>
<dl class="params">
<dt>w</dt><dd>Widget to invalidate</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtInvalidatePaint(WidgetT *w);</div>
<div class="func-body">
<p>Mark a widget as needing repaint only, without re-layout. Use for visual-only changes
(checkbox toggle, selection highlight, cursor blink).</p>
<dl class="params">
<dt>w</dt><dd>Widget to repaint</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtSetText(WidgetT *w, const char *text);</div>
<div class="func-body">
<p>Set widget text content (dispatches to the widget class's SET_TEXT handler).</p>
<dl class="params">
<dt>w</dt><dd>Widget</dd>
<dt>text</dt><dd>New text</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">const char *wgtGetText(const WidgetT *w);</div>
<div class="func-body">
<p>Get the widget's current text content.</p>
<dl class="params">
<dt>w</dt><dd>Widget</dd>
</dl>
<p><span class="label">Returns:</span> Text string (empty string if no handler)</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtSetEnabled(WidgetT *w, bool enabled);</div>
<div class="func-body">
<p>Enable or disable a widget. Disabled widgets are grayed out and do not receive input.</p>
<dl class="params">
<dt>w</dt><dd>Widget</dd>
<dt>enabled</dt><dd>true = enabled, false = disabled</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtSetReadOnly(WidgetT *w, bool readOnly);</div>
<div class="func-body">
<p>Set read-only mode. Allows scrolling and selection but blocks editing.</p>
<dl class="params">
<dt>w</dt><dd>Widget</dd>
<dt>readOnly</dt><dd>true = read-only</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtSetFocused(WidgetT *w);</div>
<div class="func-body">
<p>Set keyboard focus to a widget.</p>
<dl class="params">
<dt>w</dt><dd>Widget to focus</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">WidgetT *wgtGetFocused(void);</div>
<div class="func-body">
<p>Get the currently focused widget.</p>
<p><span class="label">Returns:</span> Focused widget, or NULL</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtSetVisible(WidgetT *w, bool visible);</div>
<div class="func-body">
<p>Show or hide a widget.</p>
<dl class="params">
<dt>w</dt><dd>Widget</dd>
<dt>visible</dt><dd>true = visible, false = hidden</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtSetName(WidgetT *w, const char *name);</div>
<div class="func-body">
<p>Set a widget's name for lookup via wgtFind().</p>
<dl class="params">
<dt>w</dt><dd>Widget</dd>
<dt>name</dt><dd>Name string (max MAX_WIDGET_NAME chars)</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">WidgetT *wgtFind(WidgetT *root, const char *name);</div>
<div class="func-body">
<p>Find a widget by name. Searches the subtree rooted at root.</p>
<dl class="params">
<dt>root</dt><dd>Root of subtree to search</dd>
<dt>name</dt><dd>Widget name to find</dd>
</dl>
<p><span class="label">Returns:</span> Matching widget, or NULL</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtDestroy(WidgetT *w);</div>
<div class="func-body">
<p>Destroy a widget and all its children. Removes from parent's child list.</p>
<dl class="params">
<dt>w</dt><dd>Widget to destroy</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtSetTooltip(WidgetT *w, const char *text);</div>
<div class="func-body">
<p>Set tooltip text for a widget. Pass NULL to remove. Caller owns the string and it
must outlive the widget.</p>
<dl class="params">
<dt>w</dt><dd>Widget</dd>
<dt>text</dt><dd>Tooltip text, or NULL</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void widgetOnResize(WindowT *win, int32_t newW, int32_t newH);</div>
<div class="func-body">
<p>Default window resize handler installed by wgtInitWindow(). Re-evaluates scrollbars
and relayouts the widget tree. Call from custom onResize handlers to chain to the
widget system.</p>
<dl class="params">
<dt>win</dt><dd>Window being resized</dd>
<dt>newW, newH</dt><dd>New content dimensions</dd>
</dl>
</div>
</div>
<h3>Layout</h3>
<div class="func">
<div class="func-sig">int32_t wgtResolveSize(int32_t taggedSize, int32_t parentSize, int32_t charWidth);</div>
<div class="func-body">
<p>Decode a tagged size value (WGT_SIZE_PIXELS/CHARS/PERCENT) into a concrete pixel count.
Returns 0 for a raw 0 input (meaning "auto").</p>
<dl class="params">
<dt>taggedSize</dt><dd>Tagged size value</dd>
<dt>parentSize</dt><dd>Parent dimension (for PERCENT mode)</dd>
<dt>charWidth</dt><dd>Font character width (for CHARS mode)</dd>
</dl>
<p><span class="label">Returns:</span> Size in pixels</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtLayout(WidgetT *root, int32_t availW, int32_t availH, const BitmapFontT *font);</div>
<div class="func-body">
<p>Execute the full two-pass layout algorithm. Pass 1 (bottom-up): compute minimum sizes.
Pass 2 (top-down): allocate space with weighted distribution. Normally called automatically;
exposed for cases where layout must be forced before the next paint.</p>
<dl class="params">
<dt>root</dt><dd>Root widget</dd>
<dt>availW, availH</dt><dd>Available space</dd>
<dt>font</dt><dd>Bitmap font (for character-based sizing)</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtPaint(WidgetT *root, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors);</div>
<div class="func-body">
<p>Paint the entire widget tree by depth-first traversal. Each widget's clip rect is set
to its bounds. Overlays (popups, tooltips) are painted in a second pass on top.</p>
<dl class="params">
<dt>root</dt><dd>Root widget</dd>
<dt>d</dt><dd>Display context</dd>
<dt>ops</dt><dd>Blit operations vtable</dd>
<dt>font</dt><dd>Bitmap font</dd>
<dt>colors</dt><dd>Color scheme</dd>
</dl>
</div>
</div>
<h3>Debug</h3>
<div class="func">
<div class="func-sig">void wgtSetDebugLayout(AppContextT *ctx, bool enabled);</div>
<div class="func-body">
<p>Draw colored borders around layout containers for debugging.</p>
<dl class="params">
<dt>ctx</dt><dd>Application context</dd>
<dt>enabled</dt><dd>true = draw debug borders</dd>
</dl>
</div>
</div>
<h3>Dynamic Widget Registration</h3>
<div class="func">
<div class="func-sig">int32_t wgtRegisterClass(const WidgetClassT *wclass);</div>
<div class="func-body">
<p>Register a new widget class at runtime. Appends to widgetClassTable. The WidgetClassT
must remain valid for the lifetime of the process (typically static const in a DXE).</p>
<dl class="params">
<dt>wclass</dt><dd>Widget class vtable to register</dd>
</dl>
<p><span class="label">Returns:</span> Assigned type ID</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtRegisterApi(const char *name, const void *api);</div>
<div class="func-body">
<p>Register a widget API struct under a name. Each widget DXE registers its API during
initialization. Callers retrieve it via wgtGetApi() and cast to the widget-specific type.</p>
<dl class="params">
<dt>name</dt><dd>Widget type name (e.g. "button", "listbox")</dd>
<dt>api</dt><dd>Pointer to the widget's API struct</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">const void *wgtGetApi(const char *name);</div>
<div class="func-body">
<p>Retrieve a registered widget API struct by name.</p>
<dl class="params">
<dt>name</dt><dd>Widget type name</dd>
</dl>
<p><span class="label">Returns:</span> Pointer to the API struct, or NULL if not found</p>
</div>
</div>
<h3>Widget Interface Descriptors</h3>
<div class="func">
<div class="func-sig">void wgtRegisterIface(const char *name, const WgtIfaceT *iface);</div>
<div class="func-body">
<p>Register an interface descriptor for a widget type. Used by the BASIC form runtime and
IDE for generic property/method dispatch.</p>
<dl class="params">
<dt>name</dt><dd>Widget type name</dd>
<dt>iface</dt><dd>Interface descriptor</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">const WgtIfaceT *wgtGetIface(const char *name);</div>
<div class="func-body">
<p>Retrieve an interface descriptor by widget type name.</p>
<dl class="params">
<dt>name</dt><dd>Widget type name</dd>
</dl>
<p><span class="label">Returns:</span> Interface descriptor, or NULL</p>
</div>
</div>
<div class="func">
<div class="func-sig">const char *wgtFindByBasName(const char *basName);</div>
<div class="func-body">
<p>Find a widget type name by its VB-style name (e.g. "CommandButton" -> "button").
Case-insensitive search.</p>
<dl class="params">
<dt>basName</dt><dd>VB-style widget name</dd>
</dl>
<p><span class="label">Returns:</span> Internal type name, or NULL</p>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t wgtIfaceCount(void);</div>
<div class="func-body">
<p>Return the number of registered widget interfaces.</p>
<p><span class="label">Returns:</span> Count of registered interfaces</p>
</div>
</div>
<div class="func">
<div class="func-sig">const WgtIfaceT *wgtIfaceAt(int32_t idx, const char **outName);</div>
<div class="func-body">
<p>Get a registered widget interface by index.</p>
<dl class="params">
<dt>idx</dt><dd>Index (0-based)</dd>
<dt>outName</dt><dd>Output: type name</dd>
</dl>
<p><span class="label">Returns:</span> Interface descriptor</p>
</div>
</div>
<div class="func">
<div class="func-sig">const char *wgtIfaceGetPath(const char *name);</div>
<div class="func-body">
<p>Get the .wgt DXE file path for a registered widget.</p>
<dl class="params">
<dt>name</dt><dd>Widget type name</dd>
</dl>
<p><span class="label">Returns:</span> File path string</p>
</div>
</div>
<div class="func">
<div class="func-sig">void wgtIfaceSetPath(const char *name, const char *path);</div>
<div class="func-body">
<p>Set the .wgt DXE file path for a registered widget (called by the loader).</p>
<dl class="params">
<dt>name</dt><dd>Widget type name</dd>
<dt>path</dt><dd>DXE file path</dd>
</dl>
</div>
</div>
<div class="func">
<div class="func-sig">int32_t wgtIfaceGetPathIndex(const char *name);</div>
<div class="func-body">
<p>Get the 1-based index of this widget within its .wgt file. Used to construct suffixed
resource names (e.g. "name-2", "icon16-2").</p>
<dl class="params">
<dt>name</dt><dd>Widget type name</dd>
</dl>
<p><span class="label">Returns:</span> 1-based index within the DXE file</p>
</div>
</div>
<h3>Typed Dispatch Helpers (Inline)</h3>
<p>The following inline functions provide type-safe dispatch through the WidgetClassT
handler table. Each checks for a non-NULL handler before calling.</p>
<table class="define-table">
<tr><th>Function</th><th>Method ID</th><th>Description</th></tr>
<tr><td>wclsHas(w, methodId)</td><td>--</td><td>Check if a handler exists for the given method ID</td></tr>
<tr><td>wclsPaint(w, d, ops, font, colors)</td><td>WGT_METHOD_PAINT</td><td>Paint the widget</td></tr>
<tr><td>wclsPaintOverlay(w, d, ops, font, colors)</td><td>WGT_METHOD_PAINT_OVERLAY</td><td>Paint overlay (popups, dropdowns)</td></tr>
<tr><td>wclsCalcMinSize(w, font)</td><td>WGT_METHOD_CALC_MIN_SIZE</td><td>Compute minimum size</td></tr>
<tr><td>wclsLayout(w, font)</td><td>WGT_METHOD_LAYOUT</td><td>Layout children</td></tr>
<tr><td>wclsGetLayoutMetrics(w, font, ...)</td><td>WGT_METHOD_GET_LAYOUT_METRICS</td><td>Get pad, gap, extraTop, borderW</td></tr>
<tr><td>wclsOnMouse(w, root, vx, vy)</td><td>WGT_METHOD_ON_MOUSE</td><td>Handle mouse event</td></tr>
<tr><td>wclsOnKey(w, key, mod)</td><td>WGT_METHOD_ON_KEY</td><td>Handle key event</td></tr>
<tr><td>wclsOnAccelActivate(w, root)</td><td>WGT_METHOD_ON_ACCEL_ACTIVATE</td><td>Handle accelerator activation</td></tr>
<tr><td>wclsDestroy(w)</td><td>WGT_METHOD_DESTROY</td><td>Destroy widget-private data</td></tr>
<tr><td>wclsOnChildChanged(parent, child)</td><td>WGT_METHOD_ON_CHILD_CHANGED</td><td>Notify parent of child change</td></tr>
<tr><td>wclsGetText(w)</td><td>WGT_METHOD_GET_TEXT</td><td>Get widget text</td></tr>
<tr><td>wclsSetText(w, text)</td><td>WGT_METHOD_SET_TEXT</td><td>Set widget text</td></tr>
<tr><td>wclsClearSelection(w)</td><td>WGT_METHOD_CLEAR_SELECTION</td><td>Clear text selection</td></tr>
<tr><td>wclsClosePopup(w)</td><td>WGT_METHOD_CLOSE_POPUP</td><td>Close dropdown popup</td></tr>
<tr><td>wclsGetPopupRect(w, font, ...)</td><td>WGT_METHOD_GET_POPUP_RECT</td><td>Get popup screen rect</td></tr>
<tr><td>wclsOnDragUpdate(w, root, x, y)</td><td>WGT_METHOD_ON_DRAG_UPDATE</td><td>Update during drag</td></tr>
<tr><td>wclsOnDragEnd(w, root, x, y)</td><td>WGT_METHOD_ON_DRAG_END</td><td>End drag operation</td></tr>
<tr><td>wclsGetCursorShape(w, vx, vy)</td><td>WGT_METHOD_GET_CURSOR_SHAPE</td><td>Get cursor shape for position</td></tr>
<tr><td>wclsPoll(w, win)</td><td>WGT_METHOD_POLL</td><td>Periodic polling (comms, etc.)</td></tr>
<tr><td>wclsQuickRepaint(w, outY, outH)</td><td>WGT_METHOD_QUICK_REPAINT</td><td>Fast partial repaint</td></tr>
<tr><td>wclsScrollChildIntoView(parent, child)</td><td>WGT_METHOD_SCROLL_CHILD_INTO_VIEW</td><td>Scroll to make child visible</td></tr>
</table>
</div>
</div> <!-- container -->
<footer>
DVX GUI API Reference -- Generated from source headers in core/*.h
</footer>
</body>
</html>