DVX_GUI/docs/dvx_system_reference.html

7189 lines
433 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Welcome!</title>
<style>
body { font-family: sans-serif; margin: 0; padding: 0; display: flex; }
nav { width: 250px; min-width: 250px; background: #f0f0f0; padding: 16px;
border-right: 1px solid #ccc; height: 100vh; overflow-y: auto;
position: sticky; top: 0; box-sizing: border-box; }
nav ul { list-style: none; padding-left: 16px; margin: 4px 0; }
nav > ul { padding-left: 0; }
nav a { text-decoration: none; color: #0066cc; }
nav a:hover { text-decoration: underline; }
main { flex: 1; padding: 24px 32px; max-width: 800px; }
h1 { border-bottom: 2px solid #333; padding-bottom: 4px; }
h2 { border-bottom: 1px solid #999; padding-bottom: 2px; margin-top: 32px; }
h3 { margin-top: 24px; }
pre { background: #f8f8f8; border: 1px solid #ddd; padding: 8px;
overflow-x: auto; font-size: 14px; }
blockquote { background: #fffde7; border-left: 4px solid #ffc107;
padding: 8px 12px; margin: 12px 0; }
hr { border: none; border-top: 1px solid #ccc; margin: 24px 0; }
img { max-width: 100%; }
.topic { margin-bottom: 48px; }
</style>
</head>
<body>
<nav>
<h3>Contents</h3>
<ul>
<li><a href="#sys.welcome">Welcome!</a></li>
<li><strong>Architecture</strong>
<ul>
<li><a href="#arch.overview">System Overview</a>
<ul>
<li><a href="#arch.layers">Five-Layer Architecture</a></li>
<li><a href="#arch.pipeline">Display Pipeline</a></li>
<li><a href="#arch.windows">Window System</a></li>
<li><a href="#arch.widgets">Widget System</a></li>
<li><a href="#arch.dialogs">Modal Dialogs</a></li>
<li><a href="#arch.resources">Resource System</a></li>
<li><a href="#arch.prefs">Preferences System</a></li>
<li><a href="#arch.memtrack">Per-App Memory Tracking</a></li>
<li><a href="#arch.dxe">DXE Module System</a></li>
<li><a href="#arch.events">Event Model</a></li>
<li><a href="#arch.fonts">Font System</a></li>
<li><a href="#arch.colors">Color System</a></li>
<li><a href="#arch.platform">Platform Layer</a></li>
<li><a href="#arch.build">Build System</a></li>
</ul>
</li>
<li><a href="#api.overview">DVX GUI API Reference</a>
<ul>
<li><a href="#api.types">dvxTypes.h -- Shared Type Definitions</a></li>
<li><a href="#api.cursor">dvxCur.h -- Cursor Definitions</a></li>
<li><a href="#api.font">dvxFont.h -- Bitmap Font Data</a></li>
<li><a href="#api.palette">dvxPal.h -- 8-bit Palette</a></li>
<li><a href="#api.video">dvxVideo.h -- Layer 1: Video Backend</a></li>
<li><a href="#api.draw">dvxDraw.h -- Layer 2: Drawing Primitives</a></li>
<li><a href="#api.comp">dvxComp.h -- Layer 3: Compositor</a></li>
<li><a href="#api.wm">dvxWm.h -- Layer 4: Window Manager</a></li>
<li><a href="#api.app">dvxApp.h -- Layer 5: Application API</a></li>
<li><a href="#api.widget">dvxWgt.h -- Widget System</a></li>
<li><a href="#api.dialog">dvxDlg.h -- Modal Dialogs</a></li>
<li><a href="#api.resource">dvxRes.h -- Resource System</a></li>
<li><a href="#api.prefs">dvxPrefs.h -- Preferences System</a></li>
<li><a href="#api.mem">dvxMem.h -- Memory Tracking</a></li>
<li><a href="#api.widgetplugin">dvxWgtP.h -- Widget Plugin API</a></li>
<li><a href="#api.platform">platform/dvxPlat.h -- Platform Layer</a></li>
</ul>
</li>
</ul>
</li>
<li><strong>Libraries</strong>
<ul>
<li><a href="#libtasks">libtasks -- Cooperative Task Switching</a></li>
<li><a href="#shell.overview">DVX Shell Library</a>
<ul>
<li><a href="#shell.types">Types and Constants</a></li>
<li><a href="#shell.lifecycle">Lifecycle API</a></li>
<li><a href="#shell.query">Query API</a></li>
<li><a href="#shell.config">Configuration API</a></li>
<li><a href="#shell.desktop">Desktop Callbacks</a></li>
<li><a href="#shell.info">System Information</a></li>
</ul>
</li>
<li><a href="#sql.overview">dvxSql -- SQL Database Interface</a>
<ul>
<li><a href="#sql.db">Database Operations</a></li>
<li><a href="#sql.cursor">Cursor Operations</a></li>
<li><a href="#sql.utility">Utility Functions</a></li>
<li><a href="#sql.example">Example Usage</a></li>
</ul>
</li>
<li><a href="#lib.texthelp">Text Help Library</a>
<ul>
<li><a href="#lib.texthelp.cursorblink">wgtUpdateCursorBlink</a></li>
<li><a href="#lib.texthelp.clearother">clearOtherSelections</a></li>
<li><a href="#lib.texthelp.iswordchar">isWordChar</a></li>
<li><a href="#lib.texthelp.wordend">wordEnd</a></li>
<li><a href="#lib.texthelp.wordstart">wordStart</a></li>
<li><a href="#lib.texthelp.wordboundaryleft">wordBoundaryLeft</a></li>
<li><a href="#lib.texthelp.wordboundaryright">wordBoundaryRight</a></li>
<li><a href="#lib.texthelp.saveundo">textEditSaveUndo</a></li>
<li><a href="#lib.texthelp.dragupdate">widgetTextEditDragUpdateLine</a></li>
<li><a href="#lib.texthelp.mouseclick">widgetTextEditMouseClick</a></li>
<li><a href="#lib.texthelp.onkey">widgetTextEditOnKey</a></li>
<li><a href="#lib.texthelp.paintline">widgetTextEditPaintLine</a></li>
</ul>
</li>
<li><a href="#lib.listhelp">List Helper Library</a></li>
<li><a href="#lib.taskmgr">Task Manager</a></li>
<li><a href="#lib.serial">Serial Stack</a>
<ul>
<li><a href="#lib.serial.rs232">RS-232 UART Driver</a></li>
<li><a href="#lib.serial.packet">Packet Transport</a></li>
<li><a href="#lib.serial.security">Security (DH + XTEA)</a></li>
<li><a href="#lib.serial.seclink">Secure Link</a></li>
<li><a href="#lib.serial.example">End-to-End Example</a></li>
</ul>
</li>
<li><a href="#lib.basrt">BASIC Runtime Library</a>
<ul>
<li><a href="#lib.basrt.values">Value System</a></li>
<li><a href="#lib.basrt.vm">Virtual Machine</a></li>
</ul>
</li>
</ul>
</li>
<li><strong>Widgets</strong>
<ul>
<li><a href="#widget.base">Widget System</a></li>
<li><a href="#widget.ansiterm">AnsiTerm</a></li>
<li><a href="#widget.box">Layout Containers</a></li>
<li><a href="#widget.box">Box (VBox / HBox / Frame)</a></li>
<li><a href="#widget.button">Button</a></li>
<li><a href="#widget.canvas">Canvas</a></li>
<li><a href="#widget.checkbox">Checkbox</a></li>
<li><a href="#widget.combobox">ComboBox</a></li>
<li><a href="#widget.datactrl">Data Widgets</a></li>
<li><a href="#widget.datactrl">DataCtrl</a></li>
<li><a href="#widget.dbgrid">DbGrid</a></li>
<li><a href="#widget.dropdown">Dropdown</a></li>
<li><a href="#widget.imagebutton">ImageButton</a></li>
<li><a href="#widget.image">Display Widgets</a></li>
<li><a href="#widget.image">Image</a></li>
<li><a href="#widget.label">Label</a></li>
<li><a href="#widget.listbox">ListBox</a></li>
<li><a href="#widget.listview">ListView</a></li>
<li><a href="#widget.progressbar">ProgressBar</a></li>
<li><a href="#widget.radio">Radio Button</a></li>
<li><a href="#widget.scrollpane">ScrollPane</a></li>
<li><a href="#widget.separator">Separator</a></li>
<li><a href="#widget.slider">Slider</a></li>
<li><a href="#widget.spacer">Spacer</a></li>
<li><a href="#widget.spinner">Spinner</a></li>
<li><a href="#widget.splitter">Splitter</a></li>
<li><a href="#widget.statusbar">StatusBar</a></li>
<li><a href="#widget.tabcontrol">TabControl</a></li>
<li><a href="#widget.textinput">Input Widgets</a></li>
<li><a href="#widget.textinput">TextInput / TextArea</a></li>
<li><a href="#widget.timer">Non-Visual Widgets</a></li>
<li><a href="#widget.timer">Timer</a></li>
<li><a href="#widget.toolbar">Container Widgets</a></li>
<li><a href="#widget.toolbar">Toolbar</a></li>
<li><a href="#widget.treeview">TreeView</a></li>
<li><a href="#widget.wrapbox">WrapBox</a></li>
</ul>
</li>
</ul>
<h3>Index</h3>
<ul>
<li><a href="#arch.overview">DVX</a></li>
<li><a href="#arch.overview">Architecture</a></li>
<li><a href="#arch.overview">DJGPP</a></li>
<li><a href="#arch.overview">DPMI</a></li>
<li><a href="#arch.layers">Layers</a></li>
<li><a href="#arch.layers">dvxVideo</a></li>
<li><a href="#arch.layers">dvxDraw</a></li>
<li><a href="#arch.layers">dvxComp</a></li>
<li><a href="#arch.layers">dvxWm</a></li>
<li><a href="#arch.layers">dvxApp</a></li>
<li><a href="#arch.pipeline">Display Pipeline</a></li>
<li><a href="#arch.pipeline">Backbuffer</a></li>
<li><a href="#arch.pipeline">Linear Framebuffer</a></li>
<li><a href="#arch.pipeline">LFB</a></li>
<li><a href="#arch.pipeline">Dirty Rects</a></li>
<li><a href="#arch.pipeline">Double Buffer</a></li>
<li><a href="#arch.pipeline">Compositing</a></li>
<li><a href="#arch.pipeline">DisplayT</a></li>
<li><a href="#arch.pipeline">BlitOpsT</a></li>
<li><a href="#arch.pipeline">DirtyListT</a></li>
<li><a href="#arch.windows">Window</a></li>
<li><a href="#arch.windows">WindowT</a></li>
<li><a href="#arch.windows">Z-Order</a></li>
<li><a href="#arch.windows">Chrome</a></li>
<li><a href="#arch.windows">Hit Testing</a></li>
<li><a href="#arch.windows">Menu System</a></li>
<li><a href="#arch.windows">Minimized Windows</a></li>
<li><a href="#arch.windows">Window Stack</a></li>
<li><a href="#arch.windows">Menus</a></li>
<li><a href="#arch.windows">Submenus</a></li>
<li><a href="#arch.widgets">Widgets</a></li>
<li><a href="#arch.widgets">WidgetT</a></li>
<li><a href="#arch.widgets">WidgetClassT</a></li>
<li><a href="#arch.widgets">Layout Engine</a></li>
<li><a href="#arch.widgets">Widget API</a></li>
<li><a href="#arch.widgets">Layout</a></li>
<li><a href="#arch.widgets">Flexbox</a></li>
<li><a href="#arch.widgets">WgtIfaceT</a></li>
<li><a href="#arch.dialogs">Dialogs</a></li>
<li><a href="#arch.dialogs">Message Box</a></li>
<li><a href="#arch.dialogs">File Dialog</a></li>
<li><a href="#arch.dialogs">Input Box</a></li>
<li><a href="#arch.resources">Resources</a></li>
<li><a href="#arch.resources">DXE Resources</a></li>
<li><a href="#arch.resources">DvxResHandleT</a></li>
<li><a href="#arch.prefs">Preferences</a></li>
<li><a href="#arch.prefs">INI files</a></li>
<li><a href="#arch.prefs">PrefsHandleT</a></li>
<li><a href="#arch.memtrack">Memory Tracking</a></li>
<li><a href="#arch.memtrack">dvxMalloc</a></li>
<li><a href="#arch.memtrack">dvxFree</a></li>
<li><a href="#arch.dxe">DXE</a></li>
<li><a href="#arch.dxe">DXE3</a></li>
<li><a href="#arch.dxe">Modules</a></li>
<li><a href="#arch.dxe">Dynamic Loading</a></li>
<li><a href="#arch.dxe">Boot Sequence</a></li>
<li><a href="#arch.dxe">Crash Recovery</a></li>
<li><a href="#arch.dxe">Memory Tracking</a></li>
<li><a href="#arch.events">Events</a></li>
<li><a href="#arch.events">Input</a></li>
<li><a href="#arch.events">Mouse</a></li>
<li><a href="#arch.events">Keyboard</a></li>
<li><a href="#arch.events">Polling</a></li>
<li><a href="#arch.events">Cooperative</a></li>
<li><a href="#arch.events">Event Dispatch</a></li>
<li><a href="#arch.events">Accelerator Tables</a></li>
<li><a href="#arch.events">Cursor</a></li>
<li><a href="#arch.events">Double-Click</a></li>
<li><a href="#arch.fonts">Fonts</a></li>
<li><a href="#arch.fonts">Bitmap Font</a></li>
<li><a href="#arch.fonts">BitmapFontT</a></li>
<li><a href="#arch.fonts">Text Rendering</a></li>
<li><a href="#arch.fonts">CP437</a></li>
<li><a href="#arch.colors">Colors</a></li>
<li><a href="#arch.colors">Pixel Format</a></li>
<li><a href="#arch.colors">PixelFormatT</a></li>
<li><a href="#arch.colors">ColorSchemeT</a></li>
<li><a href="#arch.colors">Theming</a></li>
<li><a href="#arch.colors">Bevel</a></li>
<li><a href="#arch.platform">Platform Layer</a></li>
<li><a href="#arch.platform">dvxPlat.h</a></li>
<li><a href="#arch.platform">VESA</a></li>
<li><a href="#arch.platform">VBE</a></li>
<li><a href="#arch.platform">INT 33h</a></li>
<li><a href="#arch.platform">INT 16h</a></li>
<li><a href="#arch.platform">Assembly</a></li>
<li><a href="#arch.platform">rep stosl</a></li>
<li><a href="#arch.platform">rep movsd</a></li>
<li><a href="#arch.build">Build</a></li>
<li><a href="#arch.build">Makefile</a></li>
<li><a href="#arch.build">Cross-Compilation</a></li>
<li><a href="#arch.build">dxe3gen</a></li>
<li><a href="#arch.build">mkcd.sh</a></li>
<li><a href="#arch.build">ISO</a></li>
<li><a href="#api.overview">DVX API</a></li>
<li><a href="#api.overview">API Reference</a></li>
<li><a href="#api.types">dvxTypes.h</a></li>
<li><a href="#api.types">PixelFormatT</a></li>
<li><a href="#api.types">DisplayT</a></li>
<li><a href="#api.types">RectT</a></li>
<li><a href="#api.types">BlitOpsT</a></li>
<li><a href="#api.types">BevelStyleT</a></li>
<li><a href="#api.types">BitmapFontT</a></li>
<li><a href="#api.types">ColorSchemeT</a></li>
<li><a href="#api.types">ColorIdE</a></li>
<li><a href="#api.types">DirtyListT</a></li>
<li><a href="#api.types">WindowT</a></li>
<li><a href="#api.types">WindowStackT</a></li>
<li><a href="#api.types">MenuT</a></li>
<li><a href="#api.types">MenuItemT</a></li>
<li><a href="#api.types">MenuBarT</a></li>
<li><a href="#api.types">ScrollbarT</a></li>
<li><a href="#api.types">AccelTableT</a></li>
<li><a href="#api.types">AccelEntryT</a></li>
<li><a href="#api.types">VideoModeInfoT</a></li>
<li><a href="#api.types">CursorT</a></li>
<li><a href="#api.cursor">dvxCur.h</a></li>
<li><a href="#api.cursor">Cursor Shapes</a></li>
<li><a href="#api.cursor">CURSOR_ARROW</a></li>
<li><a href="#api.cursor">CURSOR_BUSY</a></li>
<li><a href="#api.font">dvxFont.h</a></li>
<li><a href="#api.font">Font</a></li>
<li><a href="#api.font">CP437</a></li>
<li><a href="#api.font">BitmapFontT</a></li>
<li><a href="#api.palette">dvxPal.h</a></li>
<li><a href="#api.palette">Palette</a></li>
<li><a href="#api.palette">8-bit mode</a></li>
<li><a href="#api.video">dvxVideo.h</a></li>
<li><a href="#api.video">videoInit</a></li>
<li><a href="#api.video">videoShutdown</a></li>
<li><a href="#api.video">packColor</a></li>
<li><a href="#api.video">setClipRect</a></li>
<li><a href="#api.video">resetClipRect</a></li>
<li><a href="#api.video">VESA</a></li>
<li><a href="#api.video">LFB</a></li>
<li><a href="#api.draw">dvxDraw.h</a></li>
<li><a href="#api.draw">drawInit</a></li>
<li><a href="#api.draw">rectFill</a></li>
<li><a href="#api.draw">rectCopy</a></li>
<li><a href="#api.draw">rectCopyGrayscale</a></li>
<li><a href="#api.draw">drawBevel</a></li>
<li><a href="#api.draw">drawChar</a></li>
<li><a href="#api.draw">drawText</a></li>
<li><a href="#api.draw">drawTextN</a></li>
<li><a href="#api.draw">textWidth</a></li>
<li><a href="#api.draw">accelParse</a></li>
<li><a href="#api.draw">drawTextAccel</a></li>
<li><a href="#api.draw">textWidthAccel</a></li>
<li><a href="#api.draw">drawMaskedBitmap</a></li>
<li><a href="#api.draw">drawTermRow</a></li>
<li><a href="#api.draw">drawFocusRect</a></li>
<li><a href="#api.draw">drawHLine</a></li>
<li><a href="#api.draw">drawVLine</a></li>
<li><a href="#api.comp">dvxComp.h</a></li>
<li><a href="#api.comp">dirtyListInit</a></li>
<li><a href="#api.comp">dirtyListAdd</a></li>
<li><a href="#api.comp">dirtyListMerge</a></li>
<li><a href="#api.comp">dirtyListClear</a></li>
<li><a href="#api.comp">flushRect</a></li>
<li><a href="#api.comp">rectIntersect</a></li>
<li><a href="#api.comp">rectIsEmpty</a></li>
<li><a href="#api.wm">dvxWm.h</a></li>
<li><a href="#api.wm">wmInit</a></li>
<li><a href="#api.wm">wmCreateWindow</a></li>
<li><a href="#api.wm">wmDestroyWindow</a></li>
<li><a href="#api.wm">wmRaiseWindow</a></li>
<li><a href="#api.wm">wmSetFocus</a></li>
<li><a href="#api.wm">wmUpdateContentRect</a></li>
<li><a href="#api.wm">wmReallocContentBuf</a></li>
<li><a href="#api.wm">wmMinWindowSize</a></li>
<li><a href="#api.wm">wmAddMenuBar</a></li>
<li><a href="#api.wm">wmAddMenu</a></li>
<li><a href="#api.wm">wmAddMenuItem</a></li>
<li><a href="#api.wm">wmAddSubMenu</a></li>
<li><a href="#api.wm">wmCreateMenu</a></li>
<li><a href="#api.wm">wmDrawChrome</a></li>
<li><a href="#api.wm">wmHitTest</a></li>
<li><a href="#api.wm">wmDragBegin</a></li>
<li><a href="#api.wm">wmResizeBegin</a></li>
<li><a href="#api.wm">wmMaximize</a></li>
<li><a href="#api.wm">wmMinimize</a></li>
<li><a href="#api.wm">wmRestore</a></li>
<li><a href="#api.app">dvxApp.h</a></li>
<li><a href="#api.app">AppContextT</a></li>
<li><a href="#api.app">dvxInit</a></li>
<li><a href="#api.app">dvxShutdown</a></li>
<li><a href="#api.app">dvxRun</a></li>
<li><a href="#api.app">dvxUpdate</a></li>
<li><a href="#api.app">dvxQuit</a></li>
<li><a href="#api.app">dvxCreateWindow</a></li>
<li><a href="#api.app">dvxCreateWindowCentered</a></li>
<li><a href="#api.app">dvxDestroyWindow</a></li>
<li><a href="#api.app">dvxRaiseWindow</a></li>
<li><a href="#api.app">dvxFitWindow</a></li>
<li><a href="#api.app">dvxFitWindowH</a></li>
<li><a href="#api.app">dvxFitWindowW</a></li>
<li><a href="#api.app">dvxResizeWindow</a></li>
<li><a href="#api.app">dvxMinimizeWindow</a></li>
<li><a href="#api.app">dvxMaximizeWindow</a></li>
<li><a href="#api.app">dvxHideWindow</a></li>
<li><a href="#api.app">dvxShowWindow</a></li>
<li><a href="#api.app">dvxInvalidateRect</a></li>
<li><a href="#api.app">dvxInvalidateWindow</a></li>
<li><a href="#api.app">dvxSetTitle</a></li>
<li><a href="#api.app">dvxSetWindowIcon</a></li>
<li><a href="#api.app">dvxSetBusy</a></li>
<li><a href="#api.app">dvxGetFont</a></li>
<li><a href="#api.app">dvxGetColors</a></li>
<li><a href="#api.app">dvxGetDisplay</a></li>
<li><a href="#api.app">dvxGetBlitOps</a></li>
<li><a href="#api.app">dvxGetVideoModes</a></li>
<li><a href="#api.app">dvxSetColor</a></li>
<li><a href="#api.app">dvxGetColor</a></li>
<li><a href="#api.app">dvxApplyColorScheme</a></li>
<li><a href="#api.app">dvxResetColorScheme</a></li>
<li><a href="#api.app">dvxLoadTheme</a></li>
<li><a href="#api.app">dvxSaveTheme</a></li>
<li><a href="#api.app">dvxColorName</a></li>
<li><a href="#api.app">dvxColorLabel</a></li>
<li><a href="#api.app">dvxSetWallpaper</a></li>
<li><a href="#api.app">dvxSetWallpaperMode</a></li>
<li><a href="#api.app">dvxSetMouseConfig</a></li>
<li><a href="#api.app">dvxCreateAccelTable</a></li>
<li><a href="#api.app">dvxFreeAccelTable</a></li>
<li><a href="#api.app">dvxAddAccel</a></li>
<li><a href="#api.app">dvxCascadeWindows</a></li>
<li><a href="#api.app">dvxTileWindows</a></li>
<li><a href="#api.app">dvxTileWindowsH</a></li>
<li><a href="#api.app">dvxTileWindowsV</a></li>
<li><a href="#api.app">dvxLoadImage</a></li>
<li><a href="#api.app">dvxLoadImageAlpha</a></li>
<li><a href="#api.app">dvxLoadImageFromMemory</a></li>
<li><a href="#api.app">dvxFreeImage</a></li>
<li><a href="#api.app">dvxImageInfo</a></li>
<li><a href="#api.app">dvxSaveImage</a></li>
<li><a href="#api.app">dvxScreenshot</a></li>
<li><a href="#api.app">dvxWindowScreenshot</a></li>
<li><a href="#api.app">dvxClipboardCopy</a></li>
<li><a href="#api.app">dvxClipboardGet</a></li>
<li><a href="#api.app">dvxResLoadIcon</a></li>
<li><a href="#api.app">dvxResLoadText</a></li>
<li><a href="#api.app">dvxResLoadData</a></li>
<li><a href="#api.app">dvxTextHash</a></li>
<li><a href="#api.app">dvxChangeVideoMode</a></li>
<li><a href="#api.widget">dvxWgt.h</a></li>
<li><a href="#api.widget">WidgetT</a></li>
<li><a href="#api.widget">WidgetClassT</a></li>
<li><a href="#api.widget">wgtInitWindow</a></li>
<li><a href="#api.widget">wgtGetContext</a></li>
<li><a href="#api.widget">wgtInvalidate</a></li>
<li><a href="#api.widget">wgtInvalidatePaint</a></li>
<li><a href="#api.widget">wgtSetText</a></li>
<li><a href="#api.widget">wgtGetText</a></li>
<li><a href="#api.widget">wgtSetEnabled</a></li>
<li><a href="#api.widget">wgtSetReadOnly</a></li>
<li><a href="#api.widget">wgtSetFocused</a></li>
<li><a href="#api.widget">wgtGetFocused</a></li>
<li><a href="#api.widget">wgtSetVisible</a></li>
<li><a href="#api.widget">wgtSetName</a></li>
<li><a href="#api.widget">wgtFind</a></li>
<li><a href="#api.widget">wgtDestroy</a></li>
<li><a href="#api.widget">wgtSetTooltip</a></li>
<li><a href="#api.widget">wgtResolveSize</a></li>
<li><a href="#api.widget">wgtLayout</a></li>
<li><a href="#api.widget">wgtPaint</a></li>
<li><a href="#api.widget">wgtSetDebugLayout</a></li>
<li><a href="#api.widget">wgtRegisterClass</a></li>
<li><a href="#api.widget">wgtRegisterApi</a></li>
<li><a href="#api.widget">wgtGetApi</a></li>
<li><a href="#api.widget">wgtRegisterIface</a></li>
<li><a href="#api.widget">wgtGetIface</a></li>
<li><a href="#api.widget">wgtFindByBasName</a></li>
<li><a href="#api.widget">wgtPixels</a></li>
<li><a href="#api.widget">wgtChars</a></li>
<li><a href="#api.widget">wgtPercent</a></li>
<li><a href="#api.dialog">dvxDlg.h</a></li>
<li><a href="#api.dialog">dvxMessageBox</a></li>
<li><a href="#api.dialog">dvxFileDialog</a></li>
<li><a href="#api.dialog">dvxInputBox</a></li>
<li><a href="#api.dialog">dvxIntInputBox</a></li>
<li><a href="#api.dialog">dvxChoiceDialog</a></li>
<li><a href="#api.dialog">dvxPromptSave</a></li>
<li><a href="#api.dialog">dvxErrorBox</a></li>
<li><a href="#api.dialog">dvxInfoBox</a></li>
<li><a href="#api.resource">dvxRes.h</a></li>
<li><a href="#api.resource">Resources</a></li>
<li><a href="#api.resource">DvxResHandleT</a></li>
<li><a href="#api.resource">dvxResOpen</a></li>
<li><a href="#api.resource">dvxResRead</a></li>
<li><a href="#api.resource">dvxResFind</a></li>
<li><a href="#api.resource">dvxResClose</a></li>
<li><a href="#api.resource">dvxResAppend</a></li>
<li><a href="#api.resource">dvxResRemove</a></li>
<li><a href="#api.prefs">dvxPrefs.h</a></li>
<li><a href="#api.prefs">Preferences</a></li>
<li><a href="#api.prefs">PrefsHandleT</a></li>
<li><a href="#api.prefs">prefsLoad</a></li>
<li><a href="#api.prefs">prefsSave</a></li>
<li><a href="#api.prefs">prefsGetString</a></li>
<li><a href="#api.prefs">prefsGetInt</a></li>
<li><a href="#api.prefs">prefsGetBool</a></li>
<li><a href="#api.prefs">prefsSetString</a></li>
<li><a href="#api.prefs">prefsSetInt</a></li>
<li><a href="#api.prefs">prefsSetBool</a></li>
<li><a href="#api.mem">dvxMem.h</a></li>
<li><a href="#api.mem">dvxMalloc</a></li>
<li><a href="#api.mem">dvxFree</a></li>
<li><a href="#api.mem">dvxCalloc</a></li>
<li><a href="#api.mem">dvxRealloc</a></li>
<li><a href="#api.mem">dvxStrdup</a></li>
<li><a href="#api.mem">dvxMemGetAppUsage</a></li>
<li><a href="#api.mem">dvxMemResetApp</a></li>
<li><a href="#api.mem">dvxMemSnapshotLoad</a></li>
<li><a href="#api.widgetplugin">dvxWgtP.h</a></li>
<li><a href="#api.widgetplugin">widgetAlloc</a></li>
<li><a href="#api.widgetplugin">widgetAddChild</a></li>
<li><a href="#api.widgetplugin">widgetDestroyChildren</a></li>
<li><a href="#api.widgetplugin">widgetHitTest</a></li>
<li><a href="#api.widgetplugin">widgetFindNextFocusable</a></li>
<li><a href="#api.widgetplugin">widgetFindPrevFocusable</a></li>
<li><a href="#api.widgetplugin">widgetFindByAccel</a></li>
<li><a href="#api.widgetplugin">widgetDrawScrollbarH</a></li>
<li><a href="#api.widgetplugin">widgetDrawScrollbarV</a></li>
<li><a href="#api.platform">dvxPlat.h</a></li>
<li><a href="#api.platform">Platform Layer</a></li>
<li><a href="#api.platform">PlatformKeyEventT</a></li>
<li><a href="#api.platform">platformVideoInit</a></li>
<li><a href="#api.platform">platformFlushRect</a></li>
<li><a href="#api.platform">platformMousePoll</a></li>
<li><a href="#api.platform">platformKeyboardRead</a></li>
<li><a href="#api.platform">dvxLog</a></li>
<li><a href="#libtasks">libtasks</a></li>
<li><a href="#libtasks">Task Switching</a></li>
<li><a href="#libtasks">Cooperative Multitasking</a></li>
<li><a href="#libtasks">taskswitch.h</a></li>
<li><a href="#shell.overview">DVX Shell</a></li>
<li><a href="#shell.overview">shellApp.h</a></li>
<li><a href="#shell.overview">DXE Application Loading</a></li>
<li><a href="#shell.types">AppDescriptorT</a></li>
<li><a href="#shell.types">DxeAppContextT</a></li>
<li><a href="#shell.types">ShellAppT</a></li>
<li><a href="#shell.types">AppStateE</a></li>
<li><a href="#shell.types">SHELL_APP_NAME_MAX</a></li>
<li><a href="#shell.types">SHELL_STACK_DEFAULT</a></li>
<li><a href="#shell.types">SHELL_DESKTOP_APP</a></li>
<li><a href="#shell.lifecycle">shellAppInit</a></li>
<li><a href="#shell.lifecycle">shellLoadApp</a></li>
<li><a href="#shell.lifecycle">shellLoadAppWithArgs</a></li>
<li><a href="#shell.lifecycle">shellReapApps</a></li>
<li><a href="#shell.lifecycle">shellReapApp</a></li>
<li><a href="#shell.lifecycle">shellForceKillApp</a></li>
<li><a href="#shell.lifecycle">shellTerminateAllApps</a></li>
<li><a href="#shell.query">shellGetApp</a></li>
<li><a href="#shell.query">shellAppSlotCount</a></li>
<li><a href="#shell.query">shellRunningAppCount</a></li>
<li><a href="#shell.config">shellEnsureConfigDir</a></li>
<li><a href="#shell.config">shellConfigPath</a></li>
<li><a href="#shell.desktop">shellRegisterDesktopUpdate</a></li>
<li><a href="#shell.desktop">shellUnregisterDesktopUpdate</a></li>
<li><a href="#shell.desktop">shellDesktopUpdate</a></li>
<li><a href="#shell.desktop">shellCtrlEscFn</a></li>
<li><a href="#shell.info">shellInfoInit</a></li>
<li><a href="#shell.info">shellGetSystemInfo</a></li>
<li><a href="#sql.overview">dvxSql</a></li>
<li><a href="#sql.overview">SQL</a></li>
<li><a href="#sql.overview">SQLite</a></li>
<li><a href="#sql.overview">Database</a></li>
<li><a href="#sql.db">dvxSqlOpen</a></li>
<li><a href="#sql.db">dvxSqlClose</a></li>
<li><a href="#sql.db">dvxSqlExec</a></li>
<li><a href="#sql.db">dvxSqlError</a></li>
<li><a href="#sql.db">dvxSqlAffectedRows</a></li>
<li><a href="#sql.cursor">dvxSqlQuery</a></li>
<li><a href="#sql.cursor">dvxSqlNext</a></li>
<li><a href="#sql.cursor">dvxSqlEof</a></li>
<li><a href="#sql.cursor">dvxSqlFieldCount</a></li>
<li><a href="#sql.cursor">dvxSqlFieldName</a></li>
<li><a href="#sql.cursor">dvxSqlFieldText</a></li>
<li><a href="#sql.cursor">dvxSqlFieldByName</a></li>
<li><a href="#sql.cursor">dvxSqlFieldInt</a></li>
<li><a href="#sql.cursor">dvxSqlFieldDbl</a></li>
<li><a href="#sql.cursor">dvxSqlFreeResult</a></li>
<li><a href="#sql.utility">dvxSqlEscape</a></li>
<li><a href="#sql.example">SQL Example</a></li>
<li><a href="#lib.texthelp">textHelp</a></li>
<li><a href="#lib.texthelp">Text Editing</a></li>
<li><a href="#lib.texthelp">Shared Library</a></li>
<li><a href="#lib.texthelp.cursorblink">wgtUpdateCursorBlink</a></li>
<li><a href="#lib.texthelp.cursorblink">Cursor Blink</a></li>
<li><a href="#lib.texthelp.clearother">clearOtherSelections</a></li>
<li><a href="#lib.texthelp.clearother">Selection</a></li>
<li><a href="#lib.texthelp.iswordchar">isWordChar</a></li>
<li><a href="#lib.texthelp.wordend">wordEnd</a></li>
<li><a href="#lib.texthelp.wordstart">wordStart</a></li>
<li><a href="#lib.texthelp.wordboundaryleft">wordBoundaryLeft</a></li>
<li><a href="#lib.texthelp.wordboundaryleft">Word Boundary</a></li>
<li><a href="#lib.texthelp.wordboundaryright">wordBoundaryRight</a></li>
<li><a href="#lib.texthelp.wordboundaryright">Word Boundary</a></li>
<li><a href="#lib.texthelp.saveundo">textEditSaveUndo</a></li>
<li><a href="#lib.texthelp.saveundo">Undo</a></li>
<li><a href="#lib.texthelp.dragupdate">widgetTextEditDragUpdateLine</a></li>
<li><a href="#lib.texthelp.dragupdate">Drag Select</a></li>
<li><a href="#lib.texthelp.mouseclick">widgetTextEditMouseClick</a></li>
<li><a href="#lib.texthelp.mouseclick">Mouse Click</a></li>
<li><a href="#lib.texthelp.mouseclick">Multi-Click</a></li>
<li><a href="#lib.texthelp.mouseclick">Word Select</a></li>
<li><a href="#lib.texthelp.onkey">widgetTextEditOnKey</a></li>
<li><a href="#lib.texthelp.onkey">Key Handling</a></li>
<li><a href="#lib.texthelp.onkey">Text Editing</a></li>
<li><a href="#lib.texthelp.onkey">Undo</a></li>
<li><a href="#lib.texthelp.onkey">Clipboard</a></li>
<li><a href="#lib.texthelp.paintline">widgetTextEditPaintLine</a></li>
<li><a href="#lib.texthelp.paintline">Text Rendering</a></li>
<li><a href="#lib.texthelp.paintline">Selection Highlight</a></li>
<li><a href="#lib.listhelp">listhelp</a></li>
<li><a href="#lib.listhelp">widgetDrawDropdownArrow</a></li>
<li><a href="#lib.listhelp">widgetMaxItemLen</a></li>
<li><a href="#lib.listhelp">widgetNavigateIndex</a></li>
<li><a href="#lib.listhelp">widgetDropdownPopupRect</a></li>
<li><a href="#lib.listhelp">widgetPaintPopupList</a></li>
<li><a href="#lib.taskmgr">Task Manager</a></li>
<li><a href="#lib.taskmgr">shellTaskMgrOpen</a></li>
<li><a href="#lib.taskmgr">shellTaskMgrRefresh</a></li>
<li><a href="#lib.serial">Serial</a></li>
<li><a href="#lib.serial">RS-232</a></li>
<li><a href="#lib.serial">HDLC</a></li>
<li><a href="#lib.serial">XTEA</a></li>
<li><a href="#lib.serial">Diffie-Hellman</a></li>
<li><a href="#lib.serial">secLink</a></li>
<li><a href="#lib.serial.rs232">rs232</a></li>
<li><a href="#lib.serial.rs232">UART</a></li>
<li><a href="#lib.serial.rs232">COM Port</a></li>
<li><a href="#lib.serial.rs232">rs232Open</a></li>
<li><a href="#lib.serial.rs232">rs232Close</a></li>
<li><a href="#lib.serial.rs232">rs232Read</a></li>
<li><a href="#lib.serial.rs232">rs232Write</a></li>
<li><a href="#lib.serial.packet">packet</a></li>
<li><a href="#lib.serial.packet">HDLC</a></li>
<li><a href="#lib.serial.packet">CRC-16</a></li>
<li><a href="#lib.serial.packet">Go-Back-N</a></li>
<li><a href="#lib.serial.packet">pktOpen</a></li>
<li><a href="#lib.serial.packet">pktClose</a></li>
<li><a href="#lib.serial.packet">pktSend</a></li>
<li><a href="#lib.serial.packet">pktPoll</a></li>
<li><a href="#lib.serial.security">Security</a></li>
<li><a href="#lib.serial.security">Diffie-Hellman</a></li>
<li><a href="#lib.serial.security">XTEA</a></li>
<li><a href="#lib.serial.security">XTEA-CTR</a></li>
<li><a href="#lib.serial.security">DRBG</a></li>
<li><a href="#lib.serial.security">secDhCreate</a></li>
<li><a href="#lib.serial.security">secCipherCreate</a></li>
<li><a href="#lib.serial.security">secRngBytes</a></li>
<li><a href="#lib.serial.seclink">secLink</a></li>
<li><a href="#lib.serial.seclink">secLinkOpen</a></li>
<li><a href="#lib.serial.seclink">secLinkClose</a></li>
<li><a href="#lib.serial.seclink">secLinkHandshake</a></li>
<li><a href="#lib.serial.seclink">secLinkSend</a></li>
<li><a href="#lib.serial.seclink">secLinkPoll</a></li>
<li><a href="#lib.serial.example">Serial Example</a></li>
<li><a href="#lib.serial.example">BBS Client</a></li>
<li><a href="#lib.basrt">BASIC Runtime</a></li>
<li><a href="#lib.basrt">BasVmT</a></li>
<li><a href="#lib.basrt">BasValueT</a></li>
<li><a href="#lib.basrt">BasStringT</a></li>
<li><a href="#lib.basrt">BasArrayT</a></li>
<li><a href="#lib.basrt">BasModuleT</a></li>
<li><a href="#lib.basrt.values">BasValueT</a></li>
<li><a href="#lib.basrt.values">BasStringT</a></li>
<li><a href="#lib.basrt.values">BasArrayT</a></li>
<li><a href="#lib.basrt.values">BasUdtT</a></li>
<li><a href="#lib.basrt.values">basStringNew</a></li>
<li><a href="#lib.basrt.values">basArrayNew</a></li>
<li><a href="#lib.basrt.values">basValCopy</a></li>
<li><a href="#lib.basrt.values">basValRelease</a></li>
<li><a href="#lib.basrt.vm">BasVmT</a></li>
<li><a href="#lib.basrt.vm">BasModuleT</a></li>
<li><a href="#lib.basrt.vm">BasVmResultE</a></li>
<li><a href="#lib.basrt.vm">basVmCreate</a></li>
<li><a href="#lib.basrt.vm">basVmRun</a></li>
<li><a href="#lib.basrt.vm">basVmStep</a></li>
<li><a href="#lib.basrt.vm">basVmDestroy</a></li>
<li><a href="#lib.basrt.vm">basVmCallSub</a></li>
<li><a href="#widget.base">WidgetT</a></li>
<li><a href="#widget.base">Widget Base</a></li>
<li><a href="#widget.base">Common Properties</a></li>
<li><a href="#widget.base">Common Events</a></li>
<li><a href="#widget.base">wgtPixels</a></li>
<li><a href="#widget.base">wgtChars</a></li>
<li><a href="#widget.base">wgtPercent</a></li>
<li><a href="#widget.base">onClick</a></li>
<li><a href="#widget.base">onChange</a></li>
<li><a href="#widget.base">onKeyPress</a></li>
<li><a href="#widget.base">onKeyDown</a></li>
<li><a href="#widget.base">onMouseDown</a></li>
<li><a href="#widget.base">wgtInitWindow</a></li>
<li><a href="#widget.base">wgtGetContext</a></li>
<li><a href="#widget.base">wgtInvalidate</a></li>
<li><a href="#widget.base">wgtSetText</a></li>
<li><a href="#widget.base">wgtGetText</a></li>
<li><a href="#widget.base">wgtSetEnabled</a></li>
<li><a href="#widget.base">wgtSetFocused</a></li>
<li><a href="#widget.base">wgtSetVisible</a></li>
<li><a href="#widget.base">wgtFind</a></li>
<li><a href="#widget.base">wgtDestroy</a></li>
<li><a href="#widget.ansiterm">AnsiTerm</a></li>
<li><a href="#widget.ansiterm">wgtAnsiTerm</a></li>
<li><a href="#widget.ansiterm">Terminal</a></li>
<li><a href="#widget.ansiterm">VT100</a></li>
<li><a href="#widget.ansiterm">wgtAnsiTermWrite</a></li>
<li><a href="#widget.ansiterm">wgtAnsiTermClear</a></li>
<li><a href="#widget.ansiterm">wgtAnsiTermSetComm</a></li>
<li><a href="#widget.ansiterm">wgtAnsiTermSetScrollback</a></li>
<li><a href="#widget.ansiterm">wgtAnsiTermPoll</a></li>
<li><a href="#widget.ansiterm">wgtAnsiTermRepaint</a></li>
<li><a href="#widget.box">VBox</a></li>
<li><a href="#widget.box">HBox</a></li>
<li><a href="#widget.box">Frame</a></li>
<li><a href="#widget.box">wgtVBox</a></li>
<li><a href="#widget.box">wgtHBox</a></li>
<li><a href="#widget.box">wgtFrame</a></li>
<li><a href="#widget.box">Layout</a></li>
<li><a href="#widget.button">Button</a></li>
<li><a href="#widget.button">wgtButton</a></li>
<li><a href="#widget.canvas">Canvas</a></li>
<li><a href="#widget.canvas">wgtCanvas</a></li>
<li><a href="#widget.canvas">wgtCanvasClear</a></li>
<li><a href="#widget.canvas">wgtCanvasDrawLine</a></li>
<li><a href="#widget.canvas">wgtCanvasDrawRect</a></li>
<li><a href="#widget.canvas">wgtCanvasFillRect</a></li>
<li><a href="#widget.canvas">wgtCanvasFillCircle</a></li>
<li><a href="#widget.canvas">wgtCanvasSetPixel</a></li>
<li><a href="#widget.canvas">wgtCanvasGetPixel</a></li>
<li><a href="#widget.canvas">wgtCanvasDrawText</a></li>
<li><a href="#widget.canvas">wgtCanvasSave</a></li>
<li><a href="#widget.canvas">wgtCanvasLoad</a></li>
<li><a href="#widget.canvas">wgtCanvasResize</a></li>
<li><a href="#widget.canvas">wgtCanvasSetPenColor</a></li>
<li><a href="#widget.canvas">wgtCanvasSetPenSize</a></li>
<li><a href="#widget.canvas">wgtCanvasSetMouseCallback</a></li>
<li><a href="#widget.checkbox">Checkbox</a></li>
<li><a href="#widget.checkbox">wgtCheckbox</a></li>
<li><a href="#widget.checkbox">wgtCheckboxIsChecked</a></li>
<li><a href="#widget.checkbox">wgtCheckboxSetChecked</a></li>
<li><a href="#widget.combobox">ComboBox</a></li>
<li><a href="#widget.combobox">wgtComboBox</a></li>
<li><a href="#widget.combobox">wgtComboBoxSetItems</a></li>
<li><a href="#widget.combobox">wgtComboBoxAddItem</a></li>
<li><a href="#widget.combobox">wgtComboBoxRemoveItem</a></li>
<li><a href="#widget.combobox">wgtComboBoxClear</a></li>
<li><a href="#widget.combobox">wgtComboBoxGetSelected</a></li>
<li><a href="#widget.combobox">wgtComboBoxSetSelected</a></li>
<li><a href="#widget.datactrl">DataCtrl</a></li>
<li><a href="#widget.datactrl">wgtDataCtrl</a></li>
<li><a href="#widget.datactrl">Database Binding</a></li>
<li><a href="#widget.datactrl">Master-Detail</a></li>
<li><a href="#widget.datactrl">dataCtrlRefresh</a></li>
<li><a href="#widget.datactrl">dataCtrlMoveFirst</a></li>
<li><a href="#widget.datactrl">dataCtrlMoveNext</a></li>
<li><a href="#widget.datactrl">dataCtrlGetField</a></li>
<li><a href="#widget.datactrl">dataCtrlSetField</a></li>
<li><a href="#widget.datactrl">dataCtrlUpdate</a></li>
<li><a href="#widget.datactrl">dataCtrlAddNew</a></li>
<li><a href="#widget.datactrl">dataCtrlDelete</a></li>
<li><a href="#widget.dbgrid">DbGrid</a></li>
<li><a href="#widget.dbgrid">wgtDbGrid</a></li>
<li><a href="#widget.dbgrid">Database Grid</a></li>
<li><a href="#widget.dbgrid">dbGridRefresh</a></li>
<li><a href="#widget.dbgrid">dbGridSetColumnVisible</a></li>
<li><a href="#widget.dbgrid">dbGridSetColumnHeader</a></li>
<li><a href="#widget.dbgrid">dbGridSetColumnWidth</a></li>
<li><a href="#widget.dbgrid">dbGridGetSelectedRow</a></li>
<li><a href="#widget.dropdown">Dropdown</a></li>
<li><a href="#widget.dropdown">wgtDropdown</a></li>
<li><a href="#widget.dropdown">wgtDropdownSetItems</a></li>
<li><a href="#widget.dropdown">wgtDropdownAddItem</a></li>
<li><a href="#widget.dropdown">wgtDropdownRemoveItem</a></li>
<li><a href="#widget.dropdown">wgtDropdownClear</a></li>
<li><a href="#widget.dropdown">wgtDropdownGetSelected</a></li>
<li><a href="#widget.dropdown">wgtDropdownSetSelected</a></li>
<li><a href="#widget.imagebutton">ImageButton</a></li>
<li><a href="#widget.imagebutton">wgtImageButton</a></li>
<li><a href="#widget.imagebutton">wgtImageButtonFromFile</a></li>
<li><a href="#widget.imagebutton">wgtImageButtonSetData</a></li>
<li><a href="#widget.imagebutton">wgtImageButtonLoadFile</a></li>
<li><a href="#widget.image">Image</a></li>
<li><a href="#widget.image">wgtImage</a></li>
<li><a href="#widget.image">wgtImageFromFile</a></li>
<li><a href="#widget.image">wgtImageSetData</a></li>
<li><a href="#widget.image">wgtImageLoadFile</a></li>
<li><a href="#widget.image">wgtImageSetTransparent</a></li>
<li><a href="#widget.label">Label</a></li>
<li><a href="#widget.label">wgtLabel</a></li>
<li><a href="#widget.label">wgtLabelSetAlign</a></li>
<li><a href="#widget.label">wgtLabelGetAlign</a></li>
<li><a href="#widget.listbox">ListBox</a></li>
<li><a href="#widget.listbox">wgtListBox</a></li>
<li><a href="#widget.listbox">wgtListBoxAddItem</a></li>
<li><a href="#widget.listbox">wgtListBoxRemoveItem</a></li>
<li><a href="#widget.listbox">wgtListBoxClear</a></li>
<li><a href="#widget.listbox">wgtListBoxGetSelected</a></li>
<li><a href="#widget.listbox">wgtListBoxSetSelected</a></li>
<li><a href="#widget.listbox">wgtListBoxSetMultiSelect</a></li>
<li><a href="#widget.listbox">wgtListBoxIsItemSelected</a></li>
<li><a href="#widget.listbox">wgtListBoxSetReorderable</a></li>
<li><a href="#widget.listbox">wgtListBoxSelectAll</a></li>
<li><a href="#widget.listbox">wgtListBoxClearSelection</a></li>
<li><a href="#widget.listview">ListView</a></li>
<li><a href="#widget.listview">wgtListView</a></li>
<li><a href="#widget.listview">wgtListViewSetColumns</a></li>
<li><a href="#widget.listview">wgtListViewSetData</a></li>
<li><a href="#widget.listview">ListViewColT</a></li>
<li><a href="#widget.listview">ListViewSortE</a></li>
<li><a href="#widget.listview">wgtListViewGetSelected</a></li>
<li><a href="#widget.listview">wgtListViewSetSelected</a></li>
<li><a href="#widget.listview">wgtListViewSetSort</a></li>
<li><a href="#widget.listview">wgtListViewSetHeaderClickCallback</a></li>
<li><a href="#widget.listview">wgtListViewSetMultiSelect</a></li>
<li><a href="#widget.listview">wgtListViewSelectAll</a></li>
<li><a href="#widget.listview">wgtListViewClearSelection</a></li>
<li><a href="#widget.listview">wgtListViewSetReorderable</a></li>
<li><a href="#widget.progressbar">ProgressBar</a></li>
<li><a href="#widget.progressbar">wgtProgressBar</a></li>
<li><a href="#widget.progressbar">wgtProgressBarV</a></li>
<li><a href="#widget.progressbar">wgtProgressBarSetValue</a></li>
<li><a href="#widget.progressbar">wgtProgressBarGetValue</a></li>
<li><a href="#widget.radio">Radio</a></li>
<li><a href="#widget.radio">RadioGroup</a></li>
<li><a href="#widget.radio">wgtRadio</a></li>
<li><a href="#widget.radio">wgtRadioGroup</a></li>
<li><a href="#widget.radio">wgtRadioGroupSetSelected</a></li>
<li><a href="#widget.radio">wgtRadioGetIndex</a></li>
<li><a href="#widget.scrollpane">ScrollPane</a></li>
<li><a href="#widget.scrollpane">wgtScrollPane</a></li>
<li><a href="#widget.scrollpane">wgtScrollPaneScrollToChild</a></li>
<li><a href="#widget.scrollpane">wgtScrollPaneSetNoBorder</a></li>
<li><a href="#widget.separator">Separator</a></li>
<li><a href="#widget.separator">wgtHSeparator</a></li>
<li><a href="#widget.separator">wgtVSeparator</a></li>
<li><a href="#widget.slider">Slider</a></li>
<li><a href="#widget.slider">wgtSlider</a></li>
<li><a href="#widget.slider">wgtSliderSetValue</a></li>
<li><a href="#widget.slider">wgtSliderGetValue</a></li>
<li><a href="#widget.spacer">Spacer</a></li>
<li><a href="#widget.spacer">wgtSpacer</a></li>
<li><a href="#widget.spinner">Spinner</a></li>
<li><a href="#widget.spinner">wgtSpinner</a></li>
<li><a href="#widget.spinner">wgtSpinnerSetValue</a></li>
<li><a href="#widget.spinner">wgtSpinnerGetValue</a></li>
<li><a href="#widget.spinner">wgtSpinnerSetRealMode</a></li>
<li><a href="#widget.spinner">wgtSpinnerSetRange</a></li>
<li><a href="#widget.spinner">wgtSpinnerSetStep</a></li>
<li><a href="#widget.spinner">wgtSpinnerGetRealValue</a></li>
<li><a href="#widget.spinner">wgtSpinnerSetRealValue</a></li>
<li><a href="#widget.spinner">wgtSpinnerSetRealRange</a></li>
<li><a href="#widget.spinner">wgtSpinnerSetRealStep</a></li>
<li><a href="#widget.spinner">wgtSpinnerSetDecimals</a></li>
<li><a href="#widget.splitter">Splitter</a></li>
<li><a href="#widget.splitter">wgtSplitter</a></li>
<li><a href="#widget.splitter">wgtSplitterSetPos</a></li>
<li><a href="#widget.splitter">wgtSplitterGetPos</a></li>
<li><a href="#widget.statusbar">StatusBar</a></li>
<li><a href="#widget.statusbar">wgtStatusBar</a></li>
<li><a href="#widget.tabcontrol">TabControl</a></li>
<li><a href="#widget.tabcontrol">TabPage</a></li>
<li><a href="#widget.tabcontrol">wgtTabControl</a></li>
<li><a href="#widget.tabcontrol">wgtTabPage</a></li>
<li><a href="#widget.tabcontrol">wgtTabControlSetActive</a></li>
<li><a href="#widget.tabcontrol">wgtTabControlGetActive</a></li>
<li><a href="#widget.textinput">TextInput</a></li>
<li><a href="#widget.textinput">TextArea</a></li>
<li><a href="#widget.textinput">wgtTextInput</a></li>
<li><a href="#widget.textinput">wgtTextArea</a></li>
<li><a href="#widget.textinput">wgtPasswordInput</a></li>
<li><a href="#widget.textinput">wgtMaskedInput</a></li>
<li><a href="#widget.textinput">wgtTextAreaSetColorize</a></li>
<li><a href="#widget.textinput">wgtTextAreaGoToLine</a></li>
<li><a href="#widget.textinput">wgtTextAreaSetAutoIndent</a></li>
<li><a href="#widget.textinput">wgtTextAreaSetShowLineNumbers</a></li>
<li><a href="#widget.textinput">wgtTextAreaFindNext</a></li>
<li><a href="#widget.textinput">wgtTextAreaReplaceAll</a></li>
<li><a href="#widget.timer">Timer</a></li>
<li><a href="#widget.timer">wgtTimer</a></li>
<li><a href="#widget.timer">wgtTimerStart</a></li>
<li><a href="#widget.timer">wgtTimerStop</a></li>
<li><a href="#widget.timer">wgtTimerSetInterval</a></li>
<li><a href="#widget.timer">wgtTimerIsRunning</a></li>
<li><a href="#widget.timer">wgtUpdateTimers</a></li>
<li><a href="#widget.toolbar">Toolbar</a></li>
<li><a href="#widget.toolbar">wgtToolbar</a></li>
<li><a href="#widget.treeview">TreeView</a></li>
<li><a href="#widget.treeview">TreeItem</a></li>
<li><a href="#widget.treeview">wgtTreeView</a></li>
<li><a href="#widget.treeview">wgtTreeItem</a></li>
<li><a href="#widget.treeview">wgtTreeViewGetSelected</a></li>
<li><a href="#widget.treeview">wgtTreeViewSetSelected</a></li>
<li><a href="#widget.treeview">wgtTreeViewSetMultiSelect</a></li>
<li><a href="#widget.treeview">wgtTreeViewSetReorderable</a></li>
<li><a href="#widget.treeview">wgtTreeItemSetExpanded</a></li>
<li><a href="#widget.treeview">wgtTreeItemIsExpanded</a></li>
<li><a href="#widget.treeview">wgtTreeItemIsSelected</a></li>
<li><a href="#widget.treeview">wgtTreeItemSetSelected</a></li>
<li><a href="#widget.wrapbox">WrapBox</a></li>
<li><a href="#widget.wrapbox">wgtWrapBox</a></li>
</ul>
</nav>
<main>
<div class="topic" id="sys.welcome">
<h1>Welcome!</h1>
<p style="text-align:center"><img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAUAAAAB0CAYAAAD0DOulAAAAAXNSR0IB2cksfwAAAARnQU1BAACxjwv8YQUAAAAgY0hSTQAAeiYAAICEAAD6AAAAgOgAAHUwAADqYAAAOpgAABdwnLpRPAAAAAZiS0dEAAAAAAAA+UO7fwAAAAlwSFlzAAAuIwAALiMBeKU/dgAAAAd0SU1FB+oEDgIyCfl8ewwAAAyBSURBVHja7Z15jJ1VGcZ/352ZO53OdDojAwVEKAhlK5TFgmUJBMGwSCgJW4OINIZKKhqICwoxkIDIEgRNClGBoLK4gxKwGKBA2UIQEazI0kJVKC0tdoW20xn/OIO0w70zvdN7v/c953ue5P2ry33Pec77fO/Z3gPQL4vShPri14Zc9kbcb32G/XZHPRogMZEgClAC7jbk70ogi6i/MuAHhv111wBnEkCZBLGOsOTshoj66cZUxrfEIn2bB5wmbdssHGE8rTtQH4ohbQMwRQIoq9X6gK8BH5PGDYuJwHojnpYBoxz3TduYMWOsPhDrgN1TSvll+dtS4E5p3LB40JCjBUCTwz5pARYa9su9qa15yOzsNuBo6dyQeNaQnzedZetbA0sM++PpFBd9Zba2QRo3JJqA+Yb8HO+oL0427IeXqdOOrwRQton19PScKp0bEq3A84YcnemgD6Ybj9Mkd3NkvuwYaV1VfN2YG8uP1DTjtp8vAZTltUs8WVpXFTOwOx4zD2g2arfl8szZKTdQ5syyLNvQ09OzrbSuKj5vyM9cg/Y+leq0VwIoq2a3S+eqogdYbMjN7Bzb+rBhO98CxkgAZVZ2Pz7PoXnAaGC5ITdP5NBGy+M/75LjQfCSxrNQAccC96kbKmINMAF43+j39wV2beD/vxewh0XDsiyjq6vr3Lz7VhmPrJKtaXCgxY6bjfnZrwFtmmzcppuKtMsj82+9gDZFqiQshJJMlrv2O9exPbtiWwTiNozKgSnQZUPZ8q6urq2kd1XxI0Nu/lrHdrxk2I5rLQlUkMtUW3DkOMyYm6vr0IbrDf3fABwsAZR5PyT9TWldVew+sHBvxc91I5w+ZsAsQ7/fA3axJk8BLssz20gV+xhzU44w/vfyQJwCW1aLjZPWVc2mHjPk5W2guwZ/e4BFhv4+5IU0rfEIteAdYDywWl1RES8Cexv99mpgB+C/w/y9bkK9QavK08/TmGM8NUMHoYVa0QP8Xd1QFQcAzxn9djthN3eoWzwtwD+txK+zs/MZnBXd0LROpp3htOJq+hB+zdC4yZ8oIbGPU3t7e39nZ+cRoqgqzsH2YPHJFXw6HduTBNMkgEJKGfoG4HOiqCqmGvNzzgeOjB07dqaVH1mW9ZdKpROKHGBC2ssUenO4Op405OVhJ+Oo8MElpC2Cc7CrWOwdLYQjKlbcPEeoKG1Z28/t2MjrGEymOKibCHrOdA4RRRXRDfyLsEtbJKwAdiTUT3QJHYMR6oUpwB/VDRXxLrB/Adu9j2fx0xRYU+FG2G9EUVXcSnGOSd2kgJIAFlEAVwHbiaaquKYA4nd5LGRoDTBOAfSOXmASYfFd+CjWk+6m0VrsrtjVDK0BCo1AM7ouNxT2IJSCSg2rgd1iclgZoDLAPD6yWgb5KHYBXkusTeOBN2IbnILQSKiGYGXMB76VUHvOj038Ns4otAkivhppl4q2qnia+Dc9HldASQAlgEObbopURkvkIvhY7NxKAMVXHvY6Ee0OGuC+SHmNGloDFPLCToR7od3qior4eWwf4paWllOUUSgDVAaosVAvfBbbGoK11PY7UgGlQS8BHFl9uLNFY1Wcpo+YBFBIWAAH7ERRWXVZaqFj3haQ2LleCaD4sqomfYLorIh2QgUZb5wtBUan9rURBKuxd4G6oSJWEzaNFjry6TVCbb81EkBBqA8+AzzK0M84FhUr8FVf8R4SfQtaU2DxZWodHR1/E61VcbkDji5JeRoiCKZYtWrVPuqFqniEcOzECr2E2x7KKJQBKgNssEkIN8XhjrhJ8r0XlcOKUwBTxTpgApFWFUmc76eAQ42zUU2BhaRRLpfLr6gbAPits4/dp4E7NaXSFLgIfE0iHHewmm5dVXCO73C8THGrAkoCWAS+XjAOtJ8WdOnkAfyv1f5eASUBTJ2vEjDXgQgWBm1tbXuVSqUYNquWAFsroCSAReDrCcNAezelQBsGOxOuB8ayY7+OcDNEASUBTJqvo40DcwWJ3T8djHK5PA54n/iOLb0HdCmgJICp83W6caC9mbIINjU1LSDes5uPKqAkgMnzlWXZucaBliouIP4D7DMVUBLAovBlWT5rWmJcfps4KkBvToXoCxRQEsDU+erBvk7dVxLh8coEhG+wXaaAkgCmztcowgtvloE2NnIO24FXEhTAeUBbTEToLnCcAuiBL8sP28vARGB9hPy1EgqdbpPo+HwLGE84JuMeugssjBTfM/ztCcCTEfZZRrhhs03C42I74HlNqTQFLgJfs9DOcC04PsFpbzU7RgElAUydrwy4SyK4WTiMuG561GPX/iAFlAQwdb4mGgfaOmCyc85OKpDwDT4ec5z3NQltgsQngN74mgg8C5QN++VQwr3lonLmXWdcQpsgQj3wIrCbpQOtra1zu7u72531SzMwR8ODB3D88p+mwJoC14OvFuAh4ynXr5xx9WBBp76VbLYCSigCX382DrQbnfDk5Y7vRcB3nfjyZQWUkDpfGbDIONBmGXO0PeE5SesNiAs38uk7DgSwFxingBJS58v6vNvbQIcRPzsAKx2IzdoKvvU68Gu5NxGUAEoAG8HXmcaBtnIgE8sTE/FR3WUZlW+bbD8gQB4ywT09BJN2gYVG4XZsjz90AAty/s1p2B/5WEEoVb+4wp+9OfBnq4x9bAJOUUYhFIWvItwU+SE+Nhou3gxfr3Di67UKKCF1vlqB+caB1ugagpc5EZTbavDZy9vDlyighNT5asJ+R3R6owhpbm72ICT31Dj9zoD7Hfi9klAfUQElJM+XdbDVGyVCbT/rdt2yhWu11v6/brV2qk0QIU983/j3/1LHMd8xELifcNCvv9iCf/szB/7vBLyKUTVpZYDKAPPiKwOuc5Bt1CPQluHjrN+kOrRlMqGqjnV7FiughCLwFftU+DR81Pbbr46cfAof5wNPUkAJqfO1+0D2YhZspVLp6BH6Pg0fu6eXNoCXq5207RQFlJA6X+OwvzJ2QITZaz/wjwby4uW1uo8roITU+bI+i7Yuy7JDIhPAeYSnSRuFtoENCet2Pq6AEqyCL0/cbRloo0aN2tz2znaSGeVxXKTZSVvvlQAKAHR0dKT80NCjxoH2yyGEpUwote9BEGbmyMmFTto8h1BsVwKo7C/pl9asA+1PVfya4EQIzjDg5AtO2j5eAlhgZFlWhKcmpzoItKMG+bQfPspbnWc4/L7qoP29hFJjEkBlfknzdSyw3jjQtneW+S1p9BRwGLQCS530xSfrnlzkNOD1LObIhM8s6SxouyHU0xvrxJf3CcdBlhn70QP8B9tnTyEUbzihnryUchzUMmXNm5txvGz4+51OOHibcM94mQNO3iEUUn3H2I/jgKvq+R+qGILgLVtfR7gpsqDgPDzkQHAGC/IjDvz4BnCWsjNZ0plnd3f3EVmW9RWUg1lORTkDbnbQP4sIZxUlgLKkp94XFbD/b4ggO73RQT+9AYyuh6Jrl1bwNAUejCsIb9oWAfOAvSPx9VUasCtbI5YSNmi0BihsOcrlske3Lh5Y9ykCpkbk64kOfOgCTtUUWJb6zvNuGJfPysEOilCwD3HSd1/UFFhIcfq7MbYCXuPDM3opYQrwVKS+Hwk87MCPbQk71ZoCC1uE0U79Wkq4nZEaXiC8VRIrngRecuDH7JH8IwmgMBhrHPu2mPCKWSqYA+xLOPsYK9YCexIq5lhiEuHsZM3Q2pcstmWQ+xLo76cT/Hg+66Bff1frmo/WAIUPxkIsaCIULogV/cDBwDOJjaHDCbdFLMfSWsJNojc0BRZSFD8IL7LFXGDjrATFD+AxYLqxD62EM4r7awosS73owlH4eJ6yFptO+jjPSV/vKwGUJV11prOz88C2trZY+noqxcEZDvr7D8PNFLQGWNQ5b5bR39+fUp1G7+N4CeGa25KCDLFtCVf7uo39+DEwQ2uAwqZq8aH4bZNIk+Y59u3fhMKmSwo0xBYB2wFvGftxLnCNMkDhw69eqURfX19qVbrLhJsiOzjzqw8Yg+/zlY1EB7DSgR9thArbygCLPO0FUhQ/CIeJJzv068oCix/AqqEysBwxH2ivOBuSacMjIVzsqL9v0mf3/7jFAR8rCWuTEkAJX9I4D/vnLK9Dj4ENXm6b5SAWviQBlAAWATPU5y7hIR5mSgAlekXA/Qb9voY0q9bUC3sPbEZYx8eZH6SlCpZ0phjCphhLOIbRltPvrQd2JryhK1THjoQd+2ZDH5YC47QLHLfgbWzCR7F8IBvLYxe2n3D/VOI3PBYCPzH2YStg7v8AFSZzItvMm/sAAAAASUVORK5CYII=" alt="help.png"></p>
<p>DVX (DOS Visual eXecutive) is a graphical user interface environment for DOS, designed for 486-class hardware and above. This help file covers the system architecture, the core libdvx API, the widget toolkit, and the platform abstraction layer.</p>
<h2>What Is libdvx?</h2>
<p>libdvx is the heart of DVX -- a DXE3 library that provides:</p>
<ul>
<li>A VESA VBE 2.0+ video backend (LFB only, no bank switching).</li>
<li>Optimised 2D drawing primitives (rectangle fill, bevels, text, bitmap blits, cursors).</li>
<li>A dirty-rectangle compositor that minimises LFB traffic.</li>
<li>A window manager with Motif-style chrome, drag/resize, menus, and scrollbars.</li>
<li>A retained-mode widget toolkit with automatic layout.</li>
</ul>
<p>Modal dialog helpers, an INI preferences system, a DXE resource system, and per-app memory tracking.</p>
<p>Applications written in C link against libdvx (and the widget DXEs they need) to build native DVX programs. Applications written in DVX BASIC compile to bytecode that runs on top of libdvx via the form runtime.</p>
<h2>Target Audience</h2>
<p>This document is aimed at developers writing native C code for DVX:</p>
<ul>
<li>System-level contributors maintaining libdvx itself.</li>
<li>Widget authors writing new .wgt DXE modules.</li>
<li>Application authors writing .app DXE modules.</li>
</ul>
<p>Tool authors (e.g. the BASIC compiler/runtime) that sit on top of libdvx.</p>
<p>All examples and signatures assume the DJGPP cross-compiler toolchain.</p>
<h2>What's Covered</h2>
<ul>
<li>Architecture -- Five-layer model, display pipeline, event model, build system.</li>
</ul>
<p>API Reference -- Every public function, struct, enum, and constant documented with parameters and return values.</p>
<p>Use the table of contents on the left to navigate. The API reference is organised by header file; each function has a one-line summary, parameter table, and (where useful) a working example.</p>
<h2>Conventions</h2>
<ul>
<li>Types end in a capital T (e.g. WindowT, DisplayT, BlitOpsT).</li>
<li>Enum types end in a capital E (e.g. ColorIdE, WallpaperModeE, ScrollbarOrientE).</li>
<li>Public functions use camelCase and prefixes that identify the subsystem: dvx* (application), wm* (window manager), wgt* (widget), prefs* (preferences), draw* / rect* (drawing), dirtyList* / flush* (compositor), video* / packColor / setClipRect (video), platform* (platform layer).</li>
<li>Constants use SCREAMING_SNAKE_CASE (e.g. HIT_CONTENT, MB_OK, CURSOR_ARROW).</li>
</ul>
<p>Every header uses stdint.h types (int32_t, uint8_t) and stdbool.h types (bool).</p>
<h2>Getting Started</h2>
<p>If you're new to DVX, read these topics in order:</p>
<ul>
<li>Architecture Overview -- The big picture, five-layer model, and the design philosophy.</li>
<li>Display Pipeline -- How the backbuffer, dirty list, and compositor work together.</li>
<li>Event Model -- How input becomes window/widget callbacks.</li>
<li>Widget System -- The retained-mode toolkit layered on the window manager.</li>
</ul>
<p>DXE Module System -- How apps and widgets are loaded dynamically.</p>
<p>Then dip into the API Reference to find specific functions. The public entry point for any application is dvxInit / dvxRun in dvxApp.h.</p>
<h2>License</h2>
<p>DVX is distributed under the MIT License (see the copyright notice at the top of every source file). Third-party code (stb_image, stb_ds, stb_image_write in thirdparty/) is used under its own permissive license.</p>
</div>
<div class="topic" id="arch.overview">
<h1>DVX Architecture Overview</h1>
<p>DOS Visual eXecutive -- A Windowing GUI for DJGPP/DPMI</p>
<p>DVX (DOS Visual eXecutive) is a complete windowing GUI compositor targeting DJGPP/DPMI on DOS. It provides overlapping windows with Motif-style chrome, a retained-mode widget toolkit, cooperative multitasking of DXE-loaded applications, and a dirty-rectangle compositor optimized for 486/Pentium hardware.</p>
<h2>Key Design Constraints</h2>
<ul>
<li>VESA VBE 2.0+ LFB only -- no bank switching. If the hardware cannot provide a linear framebuffer, initialization fails.</li>
<li>486 baseline -- all hot paths are written to be fast on a 486, with Pentium-specific paths where the gain is significant.</li>
<li>Single-tasking cooperative model -- applications yield the CPU via tsYield(); there is no preemptive scheduler.</li>
<li>A single emulator is the trusted reference platform for testing; any bugs observed there are treated as DVX bugs.</li>
</ul>
<p>No external font or cursor files -- all bitmaps are compiled in as static const data.</p>
<p>The runtime environment consists of a bootstrap loader (dvx.exe) that loads core DXE libraries, widget plugins, and the shell, which in turn loads and manages DXE application modules.</p>
<h2>Contents</h2>
<p><a href="#arch.layers">Five-Layer Architecture</a></p>
<p><a href="#arch.pipeline">Display Pipeline</a></p>
<p><a href="#arch.windows">Window System</a></p>
<p><a href="#arch.widgets">Widget System</a></p>
<p><a href="#arch.dialogs">Modal Dialogs</a></p>
<p><a href="#arch.resources">Resource System</a></p>
<p><a href="#arch.prefs">Preferences System</a></p>
<p><a href="#arch.memtrack">Per-App Memory Tracking</a></p>
<p><a href="#arch.dxe">DXE Module System</a></p>
<p><a href="#arch.events">Event Model</a></p>
<p><a href="#arch.fonts">Font System</a></p>
<p><a href="#arch.colors">Color System</a></p>
<p><a href="#arch.platform">Platform Layer</a></p>
<p><a href="#arch.build">Build System</a></p>
</div>
<div class="topic" id="arch.layers">
<h1>Five-Layer Architecture</h1>
<p>DVX is organized into five layers, each implemented as a single .h/.c pair. Every header includes dvxTypes.h (the shared type definitions) to avoid circular dependencies. The layers are strictly stacked: each layer depends only on the layers below it.</p>
<pre><code> Applications (DXE .app modules)
==================================================
| |
| +------------------------------------------+ |
| | Layer 5: dvxApp (Application API) | | dvxApp.h / dvxApp.c
| | Event loop, window creation, public API | |
| +------------------------------------------+ |
| | Layer 4: dvxWm (Window Manager) | | dvxWm.h / dvxWm.c
| | Window stack, chrome, drag, resize | |
| +------------------------------------------+ |
| | Layer 3: dvxComp (Compositor) | | dvxComp.h / dvxComp.c
| | Dirty rect tracking, merge, LFB flush | |
| +------------------------------------------+ |
| | Layer 2: dvxDraw (Drawing Primitives) | | dvxDraw.h / dvxDraw.c
| | Rects, bevels, text, blits, cursors | |
| +------------------------------------------+ |
| | Layer 1: dvxVideo (Video Backend) | | dvxVideo.h / dvxVideo.c
| | VESA VBE, LFB mapping, pixel format | |
| +------------------------------------------+ |
| |
| +------------------------------------------+ |
| | Platform Layer (dvxPlat.h) | | dvxPlatformDos.c
| | OS-specific: video, input, asm spans | |
| +------------------------------------------+ |
| |
| +------------------------------------------+ |
| | Shared Types (dvxTypes.h) | |
| | DisplayT, WindowT, RectT, ColorSchemeT | |
| +------------------------------------------+ |
==================================================</code></pre>
<h2>Layer Summary</h2>
<pre> Layer Header Responsibility
----- ------ --------------
1 - Video dvxVideo.h VESA VBE mode negotiation, LFB mapping via DPMI, backbuffer allocation, packColor() (RGB to native pixel format), display-wide clip rectangle.
2 - Draw dvxDraw.h All 2D drawing: rectFill, rectCopy, drawBevel, drawText/drawTextN, drawMaskedBitmap (cursor), drawTermRow (batch terminal row). Stateless beyond clip rect. Dispatches hot inner loops through BlitOpsT function pointers.
3 - Compositor dvxComp.h Dirty rectangle tracking (dirtyListAdd), pairwise merge of overlapping rects (dirtyListMerge), and flushRect to copy dirty regions from backBuf to LFB.
4 - Window Manager dvxWm.h Window lifecycle, Z-order stack, chrome drawing (title bars, bevels, close/minimize/maximize gadgets), hit testing, drag/resize, menu bars, scrollbars, system menu, keyboard move/resize, minimized icon bar.
5 - Application dvxApp.h Public API aggregating all layers into AppContextT. Provides dvxInit/dvxShutdown, dvxRun/dvxUpdate, window creation helpers, image loading, clipboard, accelerator tables, theme management, wallpaper, video mode switching, screenshot capture.</pre>
</div>
<div class="topic" id="arch.pipeline">
<h1>Display Pipeline</h1>
<p>The double-buffer strategy is the single most important performance decision in DVX. All drawing goes to a system RAM backbuffer (DisplayT.backBuf); only dirty rectangles are flushed to the linear framebuffer (DisplayT.lfb) in video memory.</p>
<p>This matters because writes to video memory over the PCI bus are 10-50x slower than writes to main RAM on 486/Pentium hardware for random-access patterns.</p>
<h2>Per-Frame Compositing Pipeline</h2>
<pre><code> 1. Input poll (mouse, keyboard)
|
2. Event dispatch (focus window callbacks)
|
3. Layers call dirtyListAdd() for changed regions
|
4. dirtyListMerge() consolidates overlapping rects
|
5. For each merged dirty rect:
a. Clip and redraw desktop background (or wallpaper)
b. For each window (back-to-front, painter's algorithm):
- wmDrawChrome() -- frame, title bar, gadgets, menu bar
- wmDrawContent() -- blit per-window content buffer
- wmDrawScrollbars()
c. Draw minimized window icons
d. Draw popup menus / tooltips (overlay pass)
e. Draw software mouse cursor
|
6. flushRect() -- copy each dirty rect from backBuf to LFB
|
7. Yield (platformYield)</code></pre>
<h2>Key Data Structures</h2>
<p>DisplayT -- Central display context: width, height, pitch, pixel format, LFB pointer, backbuffer pointer, palette, clip rectangle. Passed by pointer through every layer -- no globals.</p>
<p>BlitOpsT -- Vtable of span fill/copy function pointers resolved at init time for the active pixel depth. On DOS these dispatch to hand-written rep stosl / rep movsd asm inner loops.</p>
<p>DirtyListT -- Fixed-capacity dynamic array of RectT. Linear scanning for merge candidates is cache-friendly at typical sizes (under 128 rects). If the list fills up, the compositor merges aggressively or falls back to full-screen repaint.</p>
<h2>Why This Works on a 486</h2>
<ul>
<li>A full 640x480x32bpp frame is 1.2 MB -- far too much to flush every frame over a slow PCI bus.</li>
<li>A typical dirty region during normal interaction (typing, menu open) is a few KB.</li>
<li>Merging overlapping dirty rects into larger rects reduces per-rect overhead and improves bus utilization.</li>
</ul>
<p>Per-window content buffers persist across frames, so windows don't repaint on expose -- only when their own content changes.</p>
</div>
<div class="topic" id="arch.windows">
<h1>Window System</h1>
<h2>WindowT Structure</h2>
<p>Each WindowT is the central object of the window manager. Key fields:</p>
<pre> Field Group Purpose
----------- -------
Geometry (x, y, w, h) Outer frame rectangle (including chrome).
Content area (contentX/Y/W/H) Computed from frame minus chrome. Where application content lives.
Content buffer (contentBuf, contentPitch) Per-window backbuffer in native pixel format. Persists across frames.
Chrome state (menuBar, vScroll, hScroll) Optional menu bar and scrollbars. Affect content area computation.
Widget tree (widgetRoot) Root of the retained-mode widget tree (NULL if using raw callbacks).
Callbacks onPaint, onKey, onKeyUp, onMouse, onResize, onClose, onMenu, onScroll, onFocus, onBlur, onCursorQuery.</pre>
<h2>Window Stack (Z-Order)</h2>
<p>WindowStackT is an array of WindowT* ordered front-to-back: index count-1 is the topmost window. This allows:</p>
<ul>
<li>Back-to-front iteration for painting (painter's algorithm).</li>
<li>Front-to-back iteration for hit testing (first hit wins).</li>
</ul>
<p>Reordering by pointer swap (no copying of large WindowT structs).</p>
<p>Only one drag/resize/scroll operation can be active system-wide at a time (single mouse), so that state lives on the stack, not on individual windows.</p>
<h2>Chrome Layout</h2>
<pre><code> +-------------------------------------------+
| 4px outer border (raised bevel) |
| +-------------------------------------+ |
| | [X] Title Bar Text [_] [^] [X] | | 20px title height
| +-------------------------------------+ |
| | 2px inner border | |
| +-------------------------------------+ |
| | Menu Bar (optional, 20px) | |
| +-------------------------------------+ |
| | | |
| | Content Area | |
| | | |
| | | S | | S = vertical scrollbar
| | | B | | (16px wide)
| +-------------------------------------+ |
| | Horizontal Scrollbar (optional) | | 16px tall
| +-------------------------------------+ |
| 4px outer border |
+-------------------------------------------+</code></pre>
<p>Chrome constants are compile-time defines:</p>
<pre><code> CHROME_BORDER_WIDTH = 4px
CHROME_TITLE_HEIGHT = 20px
CHROME_INNER_BORDER = 2px
CHROME_MENU_HEIGHT = 20px
SCROLLBAR_WIDTH = 16px
CHROME_CLOSE_BTN_SIZE = 16px</code></pre>
<h2>Hit Test Regions</h2>
<p>wmHitTest() iterates the stack front-to-back and returns a hit-part identifier: HIT_CONTENT, HIT_TITLE, HIT_CLOSE, HIT_RESIZE, HIT_MENU, HIT_VSCROLL, HIT_HSCROLL, HIT_MINIMIZE, HIT_MAXIMIZE. Resize edge detection returns a bitmask of RESIZE_LEFT, RESIZE_RIGHT, RESIZE_TOP, RESIZE_BOTTOM (corners combine two edges).</p>
<h2>Menu System</h2>
<p>Menus use fixed-size inline char buffers for labels (MAX_MENU_LABEL = 32, no heap strings). Both menus per bar and items per menu are stored in dynamic arrays that grow on demand. Supports cascading submenus via MenuItemT.subMenu pointer. Item types: normal, checkbox, radio. Separators are non-interactive items. The popup state (PopupStateT) tracks a stack of parent frames for cascading submenu nesting.</p>
<h2>Minimized Windows</h2>
<p>Minimized windows display as 64x64 icons at the bottom of the screen with beveled borders, similar to a classic desktop icon bar. Icons show a scaled-down preview of the window's content buffer, refreshed one per frame in a round-robin fashion to amortize the scaling cost.</p>
</div>
<div class="topic" id="arch.widgets">
<h1>Widget System</h1>
<p>The widget system (dvxWgt.h) is a retained-mode toolkit layered on top of the window manager. Widgets form a tree rooted at a per-window VBox container.</p>
<h2>WidgetT Base Structure</h2>
<p>Every widget shares the same WidgetT struct. The type field is a runtime-assigned integer ID. The wclass pointer references the widget's WidgetClassT vtable. Widget-specific private data is stored in w-&gt;data (opaque void*).</p>
<p>Tree linkage: parent, firstChild, lastChild, nextSibling. No prevSibling -- this halves pointer overhead and removal is still O(n) for typical tree depths of 5-10.</p>
<h2>Layout Engine</h2>
<p>Two-pass flexbox-like algorithm:</p>
<ul>
<li>Bottom-up (calcMinSize) -- compute minimum sizes for every widget, starting from leaves.</li>
</ul>
<p>Top-down (layout) -- allocate space within available bounds, distributing extra space according to weight values (0 = fixed, 100 = normal stretch).</p>
<p>Size hints use a tagged encoding: the top 2 bits of an int32_t select the unit (pixels, character widths, or percentage of parent), the low 30 bits hold the value. Macros: wgtPixels(v), wgtChars(v), wgtPercent(v).</p>
<h2>Widget Class Dispatch (WidgetClassT)</h2>
<p>Each widget type provides a WidgetClassT with a handlers[] array indexed by stable method IDs. Method IDs are never reordered or reused -- new methods append at the end. This provides ABI-stable dispatch so that widget DXEs compiled against an older DVX version continue to work.</p>
<p>Methods include: PAINT, PAINT_OVERLAY, CALC_MIN_SIZE, LAYOUT, ON_MOUSE, ON_KEY, ON_ACCEL_ACTIVATE, DESTROY, GET_TEXT, SET_TEXT, POLL, and more (21 defined, room for 32).</p>
<h3>Class Flags</h3>
<pre> Flag Meaning
---- -------
WCLASS_FOCUSABLE Can receive keyboard focus (Tab navigation)
WCLASS_HORIZ_CONTAINER Lays out children horizontally (HBox)
WCLASS_PAINTS_CHILDREN Widget handles child rendering itself
WCLASS_SCROLLABLE Accepts mouse wheel events
WCLASS_SCROLL_CONTAINER ScrollPane -- scrolling viewport
WCLASS_NEEDS_POLL Needs periodic polling (e.g. AnsiTerm comms)
WCLASS_SWALLOWS_TAB Tab key goes to widget, not focus navigation
WCLASS_PRESS_RELEASE Click = press + release (buttons)</pre>
<h2>Available Widget Types</h2>
<p>Each widget is a separate .wgt DXE module. 29 widget types are included:</p>
<pre> Widget Description
------ -----------
Box (VBox/HBox) Vertical and horizontal layout containers
Button Clickable push button with label
Canvas Raw drawing surface for custom painting
Checkbox Boolean toggle with checkmark
ComboBox Text input with dropdown list
DataCtrl Data-bound control for database operations
DbGrid Database grid (tabular data display)
Dropdown Dropdown selection list
Image Static image display
ImageButton Button with bitmap icon
Label Static text label
ListBox Scrollable selection list
ListView Multi-column list with headers and sorting
ProgressBar Determinate progress indicator
Radio Radio button (mutual exclusion group)
ScrollPane Scrollable viewport container
Separator Visual divider line
Slider Value selection via draggable thumb
Spacer Empty space for layout
Spinner Numeric input with up/down arrows
Splitter Resizable split pane
StatusBar Window status bar with sections
TabControl Tabbed page container
Terminal (AnsiTerm) ANSI terminal emulator widget
TextInput Single-line text entry field
Timer Periodic timer events
Toolbar Toolbar with icon buttons
TreeView Hierarchical tree display
WrapBox Flow layout (wrapping horizontal container)</pre>
<h2>Widget API Registry</h2>
<p>Each widget DXE registers a small API struct under a name during wgtRegister(). Callers retrieve it via wgtGetApi(&quot;button&quot;) and cast to the widget-specific API type. Per-widget headers provide typed accessors so callers avoid manual casts. Adding a new widget requires zero changes to the core.</p>
<h2>Widget Interface Descriptors (WgtIfaceT)</h2>
<p>Each widget can register an interface descriptor that describes its BASIC-facing properties, methods, and events. These descriptors are used by the form runtime and IDE for generic dispatch and property panel enumeration. Properties have typed getters/setters (WGT_IFACE_STRING, WGT_IFACE_INT, WGT_IFACE_BOOL, WGT_IFACE_ENUM).</p>
</div>
<div class="topic" id="arch.dialogs">
<h1>Modal Dialogs (dvxDlg.h)</h1>
<p>Pre-built modal dialog boxes block the caller and run their own event loop via dvxUpdate() until the user dismisses them. Each dialog sets ctx-&gt;modalWindow to prevent input from reaching other windows while open.</p>
<h2>Dialog Types</h2>
<pre> Function Purpose
-------- -------
dvxMessageBox Generic message box with button/icon flags (MB_OK, MB_YESNO, MB_ICONERROR, etc.)
dvxErrorBox Shortcut for MB_OK + MB_ICONERROR
dvxInfoBox Shortcut for MB_OK + MB_ICONINFO
dvxFileDialog File open/save dialog with directory navigation and filter dropdown
dvxInputBox Single-line text input with OK/Cancel
dvxIntInputBox Integer input with spinner, clamp range, and step
dvxChoiceDialog List selection with OK/Cancel
dvxPromptSave Canonical &quot;Save changes?&quot; Yes/No/Cancel dialog</pre>
<h2>Flag Encoding</h2>
<p>dvxMessageBox flags split into two nibbles: button configuration (low) and icon type (high). This matches the Win16 MessageBox() convention so OR'd flags read naturally:</p>
<pre><code>dvxMessageBox(ctx, &quot;Confirm&quot;, &quot;Delete file?&quot;, MB_YESNO | MB_ICONQUESTION);</code></pre>
<p>Return values are ID_OK / ID_CANCEL / ID_YES / ID_NO / ID_RETRY.</p>
</div>
<div class="topic" id="arch.resources">
<h1>Resource System (dvxRes.h)</h1>
<p>Resources are appended to DXE3 files (.app, .wgt, .lib) after the normal DXE content. The DXE loader never reads past the DXE header, so the appended data is invisible to dlopen. Every DXE can carry its own icons, text strings, and binary data without separate resource files.</p>
<h2>On-Disk Layout</h2>
<pre><code>[DXE3 content] -- untouched, loaded by dlopen
[resource data entries] -- sequential, variable length
[resource directory] -- fixed-size entries (48 bytes each)
[footer] -- magic + directory offset + count (16 bytes)</code></pre>
<p>Readers start from the end: seek to EOF - sizeof(footer), verify the magic (DVX_RES_MAGIC = &quot;DVXR&quot;), then seek to the directory. Entries are sorted at open time so lookups are O(log n) via bsearch.</p>
<h2>Types</h2>
<pre> Type ID Value Payload
------- ----- -------
DVX_RES_ICON 1 Image data (BMP or PNG, typically 16x16 or 32x32 icons)
DVX_RES_TEXT 2 Null-terminated string (localisable UI text, author, copyright)
DVX_RES_BINARY 3 Arbitrary data (app-specific)</pre>
<h2>Runtime API</h2>
<pre> Function Description
-------- -----------
dvxResOpen Open a handle by reading the footer and directory
dvxResRead Look up a resource by name and read its data into a malloc'd buffer
dvxResFind Look up a resource's directory entry (no data copy)
dvxResClose Release the handle
dvxResAppend Append a new resource to a DXE file
dvxResRemove Remove a resource by name</pre>
<p>The dvxApp.h wrappers (dvxResLoadIcon, dvxResLoadText, dvxResLoadData) combine open + read + close for the common case.</p>
</div>
<div class="topic" id="arch.prefs">
<h1>Preferences System (dvxPrefs.h)</h1>
<p>Handle-based API over classic INI files. Multiple files can be open at once. Each prefsLoad / prefsCreate returns a PrefsHandleT opaque pointer passed to subsequent calls and freed with prefsClose. The system INI lives at DVX_INI_PATH = &quot;CONFIG\\DVX.INI&quot;.</p>
<h2>Usage Pattern</h2>
<pre><code>PrefsHandleT *h = prefsLoad(DVX_INI_PATH);
int32_t w = prefsGetInt(h, &quot;video&quot;, &quot;width&quot;, 640);
bool sound = prefsGetBool(h, &quot;audio&quot;, &quot;enable&quot;, true);
const char *bg = prefsGetString(h, &quot;desktop&quot;, &quot;wallpaper&quot;, &quot;&quot;);
prefsSetInt(h, &quot;video&quot;, &quot;width&quot;, 800);
prefsSave(h);
prefsClose(h);</code></pre>
<p>Boolean getters recognise &quot;true&quot;/&quot;yes&quot;/&quot;1&quot; and &quot;false&quot;/&quot;no&quot;/&quot;0&quot; (case-insensitive). If the file does not exist, prefsLoad still returns a valid empty handle with the path captured so prefsSave can write a new file.</p>
</div>
<div class="topic" id="arch.memtrack">
<h1>Per-App Memory Tracking (dvxMem.h)</h1>
<p>All allocations route through dvxMalloc/dvxFree wrappers that prepend a 16-byte header recording the owning app ID and allocation size. The Task Manager displays per-app memory usage, and leaks are detected at app termination.</p>
<h2>Transparent Interception</h2>
<p>DXE code does NOT need to include dvxMem.h. The DXE export table maps malloc / free / calloc / realloc / strdup to the dvxXxx wrappers, so standard C code is tracked automatically.</p>
<p>Explicit use (e.g. in the Task Manager) can include dvxMem.h to call:</p>
<pre> Function Purpose
-------- -------
dvxMemSnapshotLoad Baseline a newly-loaded app's memory state
dvxMemGetAppUsage Query current bytes allocated for an app
dvxMemResetApp Free every tracked allocation charged to an app</pre>
<p>The dvxMemAppIdPtr pointer is set by the shell to &amp;ctx-&gt;currentAppId so the allocator always knows which app to charge.</p>
</div>
<div class="topic" id="arch.dxe">
<h1>DXE Module System</h1>
<p>DVX uses DJGPP's DXE3 (Dynamic eXtension) format for all loadable modules. DXE3 supports RTLD_GLOBAL symbol sharing -- symbols exported by one module are visible to all subsequently loaded modules. This is critical: widget DXEs call core API functions (e.g. rectFill, wgtInvalidate) that are exported by the core library DXE.</p>
<h2>Module Types</h2>
<pre> Extension Directory Purpose Examples
--------- --------- ------- --------
.lib LIBS/ Core libraries loaded first. Provide infrastructure APIs. libtasks.lib, libdvx.lib, dvxshell.lib
.wgt WIDGETS/ Widget type plugins. Each exports wgtRegister(). button.wgt, listview.wgt, terminal.wgt
.app APPS/*/ Application modules. Each exports appDescriptor and appMain(). Loaded on demand by the shell. progman.app, notepad.app, cpanel.app</pre>
<h2>Boot Sequence</h2>
<pre><code> dvx.exe (loader)
|
+-- Enter VGA mode 13h, display splash screen with progress bar
|
+-- Scan LIBS/ for *.lib, WIDGETS/ for *.wgt
|
+-- Read .dep files for each module (dependency base names)
|
+-- Topological sort: load modules in dependency order
| - dlopen() with RTLD_GLOBAL
| - Each .wgt that exports wgtRegister() has it called
|
+-- Find and call shellMain() (exported by dvxshell.lib)
|
+-- dvxInit() -- video mode, input, font, colors, cursors
|
+-- Load desktop app (progman.app)
|
+-- Main loop:
dvxUpdate() -&gt; tsYield() -&gt; shellReapApps()</code></pre>
<h2>Application Lifecycle</h2>
<p>Two kinds of DXE apps:</p>
<h3>Callback-only (hasMainLoop = false)</h3>
<p>appMain() creates windows, registers callbacks, and returns. The app lives through GUI callbacks driven by the shell's main loop. Lifecycle ends when the last window is closed. No extra task stack needed -- simpler and cheaper.</p>
<h3>Main-loop (hasMainLoop = true)</h3>
<p>A dedicated cooperative task is created. appMain() runs in that task with its own loop, calling tsYield() to share CPU. Needed for apps with continuous work (terminal emulators, games). Lifecycle ends when appMain() returns.</p>
<h2>Crash Recovery</h2>
<p>The platform layer installs signal handlers for SIGSEGV, SIGFPE, SIGILL. On crash, the handler logs platform-specific diagnostics (register dump on DJGPP), then longjmps back to the shell's main loop. The crashed app is killed; other apps and the shell survive. This provides Windows 3.1-style fault tolerance.</p>
<h2>Per-App Memory Tracking</h2>
<p>All allocations route through dvxMalloc/dvxFree wrappers that prepend a 16-byte header recording the owning app ID and allocation size. The Task Manager displays per-app memory usage, and leaks are detected at app termination.</p>
</div>
<div class="topic" id="arch.events">
<h1>Event Model</h1>
<p>DVX uses a cooperative polling model. The main loop (dvxRun / dvxUpdate) runs this cycle each frame:</p>
<ul>
<li>Poll mouse -- platformMousePoll() returns position and button bitmask. Compare with previous frame for press/release edge detection.</li>
<li>Poll keyboard -- platformKeyboardRead() returns ASCII + scancode. Non-blocking; returns false if buffer is empty.</li>
<li>Dispatch to focused window -- the event loop fires window callbacks (onKey, onMouse, etc.) on the focused window. If the window has a widget tree, the widget system's installed handlers dispatch to individual widgets.</li>
<li>Compositor pass -- merge dirty rects, composite, flush to LFB.</li>
</ul>
<p>Yield -- platformYield() or idle callback.</p>
<h2>Event Dispatch Chain</h2>
<pre><code> Mouse/Keyboard Input
|
Global handlers (Ctrl+Esc, modal filter)
|
Accelerator table check (focused window)
|
Window callback (onMouse / onKey)
|
[If widget tree installed:]
|
widgetOnMouse / widgetOnKey
|
Widget hit test (widgetHitTest)
|
wclsOnMouse / wclsOnKey (vtable dispatch)
|
Universal callbacks (onClick, onChange, etc.)</code></pre>
<h2>Accelerator Tables</h2>
<p>Per-window accelerator tables map key + modifier combinations to command IDs. The runtime normalizes key/modifier at registration time (uppercase key, strip shift from modifiers) so matching at dispatch time is two integer comparisons per entry. Matched accelerators fire the window's onMenu callback with the command ID, unifying the menu and hotkey code paths.</p>
<h2>Mouse Cursor</h2>
<p>Software-rendered cursor using the classic AND/XOR mask approach. Seven cursor shapes are compiled in: arrow, horizontal resize, vertical resize, NW-SE diagonal resize, NE-SW diagonal resize, busy (hourglass), and crosshair. The cursor is painted into the backbuffer on top of the composited frame and the affected region is flushed to the LFB each frame.</p>
<h2>Double-Click Detection</h2>
<p>Timestamp-based: two clicks on the same target (title bar, minimized icon, close gadget) within the configurable double-click interval trigger the double-click action. Separate tracking for each target type.</p>
</div>
<div class="topic" id="arch.fonts">
<h1>Font System</h1>
<p>DVX uses fixed-width 8-pixel-wide bitmap fonts only. One size is provided: 8x16, matching the standard VGA ROM font and CP437 encoding (256 glyphs).</p>
<h2>BitmapFontT</h2>
<pre><code> typedef struct {
int32_t charWidth; // fixed width per glyph (always 8)
int32_t charHeight; // 16
int32_t firstChar; // typically 0
int32_t numChars; // typically 256
const uint8_t *glyphData; // packed 1bpp, charHeight bytes per glyph
} BitmapFontT;</code></pre>
<p>Design rationale:</p>
<ul>
<li>Character positions are pure multiplication (x = col * 8).</li>
<li>Glyph lookup is a single array index.</li>
<li>Each scanline of a glyph is exactly one byte (1bpp at 8 pixels wide).</li>
<li>No glyph-width tables, kerning, or per-character positioning needed.</li>
</ul>
<p>8-pixel width aligns with byte boundaries -- no bit shifting in per-scanline rendering.</p>
<h2>Text Rendering Functions</h2>
<p>drawChar() -- Renders a single character. Supports opaque (background fill) and transparent modes.</p>
<p>drawTextN() -- Optimized batch rendering for a known character count. Clips once for the entire run, fills background in a single rectFill, then overlays glyph foreground pixels. Significantly faster than per-character rendering for long runs.</p>
<p>drawTermRow() -- Renders an 80-column terminal row in a single pass, with per-cell foreground/background from a 16-color palette, blink attribute support, and cursor rendering. Exists because per-character terminal rendering is unacceptably slow on target hardware.</p>
<p>drawTextAccel() -- Renders text with &amp; accelerator markers. The character after &amp; is underlined to indicate the keyboard shortcut.</p>
<h2>Performance Optimization</h2>
<p>AppContextT stores a fixed-point 16.16 reciprocal of font.charHeight (charHeightRecip) so that dividing by charHeight (for pixel-to-row conversion in terminal/text widgets) becomes a multiply+shift instead of an integer divide, which costs 40+ cycles on a 486.</p>
</div>
<div class="topic" id="arch.colors">
<h1>Color System</h1>
<h2>Pixel Format</h2>
<p>PixelFormatT describes the active VESA mode's pixel encoding. Populated once from the VBE mode info block. Stores shift, mask, and bit count for each channel so packColor() can convert RGB to native format with shift-and-mask arithmetic -- no per-pixel computation.</p>
<p>Supported depths:</p>
<pre> Depth Bytes/Pixel Notes
----- ----------- -----
8 bpp 1 Palette mode. Nearest-index via 6x6x6 color cube + grey ramp.
15 bpp 2 5-5-5 RGB (1 bit unused).
16 bpp 2 5-6-5 RGB.
32 bpp 4 8-8-8 RGB (8 bits unused).</pre>
<h2>ColorSchemeT -- Theming</h2>
<p>All 20 UI colors are pre-packed into display pixel format at init time. Every color is a uint32_t that can be written directly to the framebuffer with zero per-pixel conversion. The scheme must be regenerated on video mode change, but mode changes require re-init anyway.</p>
<p>Color roles mirror classic Motif/Windows 3.x conventions:</p>
<ul>
<li>desktop -- desktop background</li>
<li>windowFace, windowHighlight, windowShadow -- window chrome bevel triplet</li>
<li>activeTitleBg/Fg, inactiveTitleBg/Fg -- focused vs. unfocused title bar</li>
<li>contentBg/Fg -- window content area</li>
<li>menuBg/Fg, menuHighlightBg/Fg -- menus</li>
<li>buttonFace -- button background</li>
<li>scrollbarBg/Fg/Trough -- scrollbar components</li>
</ul>
<p>cursorFg/Bg -- mouse cursor colors</p>
<p>Source RGB values are kept in AppContextT.colorRgb[] for theme save/load. Themes are stored as INI files with a [colors] section. The API provides dvxLoadTheme(), dvxSaveTheme(), dvxSetColor(), and dvxResetColorScheme().</p>
<h2>Bevel Styles</h2>
<p>Bevels are the defining visual element of the Motif aesthetic. Convenience macros create bevel style descriptors by swapping highlight and shadow colors:</p>
<pre><code> BEVEL_RAISED(colorScheme, borderWidth) -- raised 3D look
BEVEL_SUNKEN(colorScheme, face, borderWidth) -- sunken/inset look
BEVEL_TROUGH(colorScheme) -- 1px scrollbar trough
BEVEL_SB_BUTTON(colorScheme) -- scrollbar button</code></pre>
</div>
<div class="topic" id="arch.platform">
<h1>Platform Layer</h1>
<p>All OS-specific and CPU-specific code is isolated behind platform/dvxPlat.h. To port DVX, implement a new dvxPlatformXxx.c against this header.</p>
<h2>Implementations</h2>
<pre> File Target Details
---- ------ -------
dvxPlatformDos.c DJGPP/DPMI Real VESA VBE, INT 33h mouse, INT 16h keyboard, rep movsd/rep stosl asm spans, DPMI physical memory mapping for LFB, INT 9 hook for key-up, CuteMouse Wheel API.</pre>
<h2>Abstraction Areas</h2>
<h3>Video</h3>
<p>platformVideoInit() -- mode probe and framebuffer setup. platformVideoShutdown() -- restore previous mode. platformVideoEnumModes() -- enumerate available modes.</p>
<h3>Framebuffer Flush</h3>
<p>platformFlushRect() -- copy dirty rect from backBuf to LFB. On DOS, each scanline uses rep movsd for near-optimal aligned 32-bit writes over the PCI bus.</p>
<h3>Optimized Memory Spans</h3>
<p>Six functions: platformSpanFill8/16/32() and platformSpanCopy8/16/32(). Called once per scanline of every rectangle fill, blit, and text draw. On DOS these use inline assembly for critical inner loops.</p>
<h3>Mouse Input</h3>
<p>Polling model. platformMousePoll() returns position and button bitmask. Wheel support via CuteMouse API.</p>
<h3>Keyboard Input</h3>
<p>platformKeyboardRead() -- non-blocking key read. platformKeyUpRead() -- key release detection (requires INT 9 hook on DOS). platformAltScanToChar() -- scancode-to-ASCII lookup for Alt+key combinations.</p>
<h3>Crash Recovery</h3>
<p>platformInstallCrashHandler() -- signal handlers + longjmp for fault tolerance.</p>
<h3>DXE Support</h3>
<p>platformRegisterDxeExports() -- register C runtime and platform symbols for DXE resolution. platformRegisterSymOverrides() -- register function pointer overrides for module loader.</p>
</div>
<div class="topic" id="arch.build">
<h1>Build System</h1>
<h2>Cross-Compilation</h2>
<p>DVX is cross-compiled from Linux using a DJGPP cross-compiler (i586-pc-msdosdjgpp-gcc). The top-level Makefile orchestrates building all subsystems in dependency order.</p>
<pre><code> make -- build everything
./mkcd.sh -- build + create ISO for the target emulator</code></pre>
<h2>Build Targets</h2>
<pre><code> all: core tasks loader texthelp listhelp tools widgets shell taskmgr serial sql apps</code></pre>
<pre> Target Output Description
------ ------ -----------
core bin/libs/libdvx.lib GUI core library (draw, comp, wm, app, widget infrastructure)
tasks bin/libs/libtasks.lib Cooperative task switcher
loader bin/dvx.exe Bootstrap loader (the DOS executable)
widgets bin/widgets/*.wgt 29 widget type plugins
shell bin/libs/dvxshell.lib DVX Shell (app management, desktop)
taskmgr bin/libs/taskmgr.lib Task Manager (loaded as a separate DXE)
texthelp shared library Shared text editing helpers (clipboard, word boundaries)
listhelp shared library Shared dropdown/list helpers
apps bin/apps/*/*.app Application modules (progman, notepad, clock, etc.)
tools bin/dvxres Resource compiler (runs on Linux, builds resource sections into DXEs)
serial serial DXE libs UART driver, HDLC packets, security, seclink
sql SQL DXE lib SQLite integration</pre>
<h2>DXE3 Build Process</h2>
<p>Each DXE module is compiled to an object file with GCC, then linked with dxe3gen:</p>
<pre><code> # Compile
i586-pc-msdosdjgpp-gcc -O2 -march=i486 -mtune=i586 -c -o widget.o widget.c
# Link as DXE (exports all non-static symbols)
dxe3gen -o widget.wgt -U widget.o
# Optionally append resources
dvxres build widget.wgt widget.res</code></pre>
<p>The -E flag specifies exported symbols (prefixed with underscore per DJGPP convention). -U marks unresolved symbols as OK (they'll be resolved at load time from previously loaded DXEs).</p>
<h2>Deployment (mkcd.sh)</h2>
<ul>
<li>Runs make all.</li>
<li>Verifies critical outputs exist (dvx.exe, libtasks.lib, libdvx.lib, dvxshell.lib).</li>
<li>Counts widget modules.</li>
<li>Creates an ISO 9660 image from bin/ using mkisofs: -iso-level 1 (strict 8.3 filenames for DOS), -J (Joliet extensions for long names), -V DVX (volume label).</li>
</ul>
<p>Places the ISO at the target emulator's CD-ROM mount path.</p>
<h2>Compiler Flags</h2>
<pre><code> -O2 Optimization level 2
-march=i486 486 instruction set baseline
-mtune=i586 Optimize scheduling for Pentium
-Wall -Wextra Full warnings</code></pre>
<h2>Directory Layout</h2>
<pre><code> dvxgui/
+-- core/ Core library sources (dvxVideo, dvxDraw, dvxComp, dvxWm, dvxApp, widget infra)
| +-- platform/ Platform abstraction (dvxPlat.h, dvxPlatformDos.c, dvxPlatformUtil.c)
| +-- thirdparty/ stb_image, stb_ds, stb_image_write
+-- loader/ Bootstrap loader (dvx.exe)
+-- tasks/ Cooperative task switcher (libtasks.lib)
+-- shell/ DVX Shell (dvxshell.lib)
+-- widgets/ Widget DXE modules (*.wgt), each in its own subdirectory
| +-- box/ VBox/HBox layout containers
| +-- button/ Push button
| +-- textInput/ Text entry field
| +-- listView/ Multi-column list
| +-- ... (29 widget types total)
+-- texthelp/ Shared text editing helpers
+-- listhelp/ Shared dropdown/list helpers
+-- apps/ Application DXE modules (*.app)
| +-- progman/ Program Manager (desktop)
| +-- notepad/ Text editor
| +-- cpanel/ Control Panel
| +-- imgview/ Image viewer
| +-- clock/ Clock
| +-- dvxdemo/ Demo / showcase app
| +-- dvxbasic/ DVX BASIC compiler and VM
+-- tools/ Build tools (dvxres resource compiler)
+-- rs232/ ISR-driven UART driver
+-- packet/ HDLC framing, CRC-16, sliding window
+-- security/ DH key exchange, XTEA cipher, DRBG RNG
+-- seclink/ Encrypted channel wrapper
+-- serial/ Combined serial stack DXE
+-- proxy/ Linux proxy (emulator &lt;-&gt; secLink &lt;-&gt; telnet)
+-- sql/ SQLite integration
+-- bin/ Build output (dvx.exe, libs/, widgets/, apps/, config/)
+-- obj/ Intermediate object files
+-- docs/ Documentation</code></pre>
</div>
<div class="topic" id="api.overview">
<h1>DVX GUI API Reference</h1>
<p>DOS Visual eXecutive -- Complete public API documentation covering every public function, type, and constant in the libdvx headers.</p>
<p>The DVX GUI is built as a five-layer architecture. Each layer is defined in its own header file. Additional headers cover dialogs, resources, preferences, memory tracking, the platform abstraction, and the widget system.</p>
<h2>Headers</h2>
<ul>
<li>dvxTypes.h -- Shared type definitions and constants</li>
<li>dvxCur.h -- Embedded mouse cursor bitmaps</li>
<li>dvxFont.h -- Embedded 8x16 CP437 bitmap font</li>
<li>dvxPal.h -- 8-bit mode 256-color palette</li>
<li>dvxVideo.h -- Layer 1: VESA VBE video backend</li>
<li>dvxDraw.h -- Layer 2: 2D drawing primitives</li>
<li>dvxComp.h -- Layer 3: Dirty rectangle compositor</li>
<li>dvxWm.h -- Layer 4: Window manager</li>
<li>dvxApp.h -- Layer 5: Application API</li>
<li>dvxDlg.h -- Modal dialog boxes</li>
<li>dvxRes.h -- DXE-embedded resource system</li>
<li>dvxPrefs.h -- INI preferences system</li>
<li>dvxMem.h -- Per-app memory tracking</li>
<li>dvxWgt.h -- Widget system public API</li>
<li>dvxWgtP.h -- Widget plugin API</li>
</ul>
<p>platform/dvxPlat.h -- Platform abstraction layer</p>
<p><a href="#api.types">dvxTypes.h -- Shared Type Definitions</a></p>
<p><a href="#api.cursor">dvxCur.h -- Cursor Definitions</a></p>
<p><a href="#api.font">dvxFont.h -- Bitmap Font Data</a></p>
<p><a href="#api.palette">dvxPal.h -- 8-bit Palette</a></p>
<p><a href="#api.video">dvxVideo.h -- Layer 1: Video Backend</a></p>
<p><a href="#api.draw">dvxDraw.h -- Layer 2: Drawing Primitives</a></p>
<p><a href="#api.comp">dvxComp.h -- Layer 3: Compositor</a></p>
<p><a href="#api.wm">dvxWm.h -- Layer 4: Window Manager</a></p>
<p><a href="#api.app">dvxApp.h -- Layer 5: Application API</a></p>
<p><a href="#api.dialog">dvxDlg.h -- Modal Dialogs</a></p>
<p><a href="#api.resource">dvxRes.h -- Resource System</a></p>
<p><a href="#api.prefs">dvxPrefs.h -- Preferences</a></p>
<p><a href="#api.mem">dvxMem.h -- Memory Tracking</a></p>
<p><a href="#api.widget">dvxWgt.h -- Widget System</a></p>
<p><a href="#api.widgetplugin">dvxWgtP.h -- Widget Plugin API</a></p>
<p><a href="#api.platform">platform/dvxPlat.h -- Platform Layer</a></p>
</div>
<div class="topic" id="api.types">
<h1>dvxTypes.h -- Shared Type Definitions</h1>
<p>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>
<h2>Core Structures</h2>
<h3>PixelFormatT</h3>
<p>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.</p>
<pre> Field Description
----- -----------
int32_t bitsPerPixel 8, 15, 16, or 32
int32_t bytesPerPixel 1, 2, 2, or 4
uint32_t redMask, greenMask, blueMask Bitmasks for each color channel
int32_t redShift, greenShift, blueShift Bit position of each color field
int32_t redBits, greenBits, blueBits Number of bits per channel</pre>
<h3>DisplayT</h3>
<p>Single display context passed by pointer through every layer. All drawing targets the backBuf; only dirty rects are flushed to lfb.</p>
<pre> Field Description
----- -----------
int32_t width, height Screen dimensions in pixels
int32_t pitch Bytes per scanline
PixelFormatT format Active pixel format
uint8_t *lfb Mapped linear framebuffer (VESA LFB)
uint8_t *backBuf System RAM backbuffer
uint8_t *palette 768 bytes for 8-bit mode, NULL otherwise
int32_t clipX, clipY, clipW, clipH Current clip rectangle</pre>
<h3>RectT</h3>
<p>Rectangle in origin + extent form. Used throughout the compositor, window manager, and widget layout engine.</p>
<pre> Field Description
----- -----------
int32_t x, y Top-left corner
int32_t w, h Width and height</pre>
<h3>BlitOpsT</h3>
<p>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).</p>
<pre> Field Description
----- -----------
SpanFillFnT spanFill Fill a horizontal span with a solid color
SpanCopyFnT spanCopy Copy a horizontal span between buffers
int32_t bytesPerPixel Bytes per pixel for the active mode
int32_t pitch Bytes per scanline</pre>
<h3>BevelStyleT</h3>
<p>Bevel drawing parameters. Swapping highlight/shadow flips raised vs. sunken appearance.</p>
<pre> Field Description
----- -----------
uint32_t highlight Lighter color (top/left edges)
uint32_t shadow Darker color (bottom/right edges)
uint32_t face Interior fill color (0 = no fill)
int32_t width Border thickness in pixels (typically 2)</pre>
<h3>BitmapFontT</h3>
<p>Fixed-width 8-pixel-wide bitmap font descriptor. One size provided: 8x16 (standard VGA ROM font, CP437 encoding).</p>
<pre> Field Description
----- -----------
int32_t charWidth Fixed width per glyph (always 8)
int32_t charHeight Glyph height (16 in the bundled font)
int32_t firstChar ASCII code of first glyph (typically 0)
int32_t numChars Number of glyphs (typically 256)
const uint8_t *glyphData Packed 1bpp data, charHeight bytes per glyph</pre>
<h3>ColorSchemeT</h3>
<p>All UI colors pre-packed into display pixel format at init time. Theme support is achieved by swapping this struct.</p>
<pre> Field Description
----- -----------
uint32_t desktop Desktop background color
uint32_t windowFace Window body / chrome face
uint32_t windowHighlight Bevel highlight (top/left edge)
uint32_t windowShadow Bevel shadow (bottom/right edge)
uint32_t activeTitleBg, activeTitleFg Focused window title bar
uint32_t inactiveTitleBg, inactiveTitleFg Unfocused window title bar
uint32_t contentBg, contentFg Window content area default colors
uint32_t menuBg, menuFg Menu bar and popup background/text
uint32_t menuHighlightBg, menuHighlightFg Menu item highlight
uint32_t buttonFace Button face color
uint32_t scrollbarBg, scrollbarFg, scrollbarTrough Scrollbar element colors
uint32_t cursorFg, cursorBg Mouse cursor colors</pre>
<h3>ColorIdE</h3>
<p>Enum for addressing individual colors in ColorSchemeT. Order matches struct field order.</p>
<p>Values: ColorDesktopE, ColorWindowFaceE, ColorWindowHighlightE, ColorWindowShadowE, ColorActiveTitleBgE, ColorActiveTitleFgE, ColorInactiveTitleBgE, ColorInactiveTitleFgE, ColorContentBgE, ColorContentFgE, ColorMenuBgE, ColorMenuFgE, ColorMenuHighlightBgE, ColorMenuHighlightFgE, ColorButtonFaceE, ColorScrollbarBgE, ColorScrollbarFgE, ColorScrollbarTroughE, ColorCursorFgE, ColorCursorBgE, ColorCountE.</p>
<h3>DirtyListT</h3>
<p>Fixed-capacity list of dirty rectangles. Dynamic array, grows on demand.</p>
<pre> Field Description
----- -----------
RectT *rects Dynamic array of dirty rectangles
int32_t count Current number of dirty rects
int32_t cap Allocated capacity</pre>
<h3>WindowT</h3>
<p>Central window object. Each window owns a persistent content backbuffer and receives events through callback function pointers.</p>
<pre> Field Description
----- -----------
int32_t id Unique window identifier
int32_t appId Shell app ID (0 = shell itself)
int32_t x, y, w, h Outer frame position and dimensions
int32_t contentX, contentY, contentW, contentH Content area inset from frame
char title[MAX_TITLE_LEN] Window title text (max 128 chars)
bool visible, focused, minimized, maximized, resizable, modal Window state flags
bool iconNeedsRefresh true when contentBuf changed (for minimized icon refresh)
uint8_t paintNeeded PAINT_NONE / PAINT_PARTIAL / PAINT_FULL
int32_t maxW, maxH Maximum dimensions
int32_t preMaxX, preMaxY, preMaxW, preMaxH Saved geometry before maximize
uint8_t *contentBuf Per-window content backbuffer
int32_t contentPitch Content buffer bytes per row
uint8_t *iconData Icon pixel data, NULL if none
int32_t iconW, iconH, iconPitch Icon image dimensions and pitch
MenuBarT *menuBar Menu bar (NULL if no menus)
ScrollbarT *vScroll, *hScroll Scrollbars (NULL if not present)
struct WidgetT *widgetRoot Widget tree root (NULL if none)
MenuT *contextMenu Right-click context menu
AccelTableT *accelTable Keyboard accelerator table
void *userData Application-defined data pointer</pre>
<p>Callbacks:</p>
<pre> Callback Description
-------- -----------
onPaint(WindowT *win, RectT *dirtyArea) Content repaint requested
onKey(WindowT *win, int32_t key, int32_t mod) Key press
onKeyUp(WindowT *win, int32_t scancode, int32_t mod) Key release
onMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons) Mouse event (content-relative)
onResize(WindowT *win, int32_t newW, int32_t newH) Window resized
onClose(WindowT *win) Close requested
onMenu(WindowT *win, int32_t menuId) Menu item or accelerator activated
onScroll(WindowT *win, ScrollbarOrientE orient, int32_t value) Scrollbar value changed
int32_t onCursorQuery(WindowT *win, int32_t x, int32_t y) Return CURSOR_* for hit position
onFocus(WindowT *win) Window gained focus
onBlur(WindowT *win) Window lost focus</pre>
<h3>WindowStackT</h3>
<p>Z-ordered window stack (front-to-back: index count-1 is topmost). Owns system-wide drag/resize/scroll interaction state.</p>
<pre> Field Description
----- -----------
WindowT **windows Dynamic array of window pointers
int32_t count, cap Current count and allocated capacity
int32_t focusedIdx Stack index of focused window
int32_t dragWindow, dragOffX, dragOffY Active drag state
int32_t dragStartX, dragStartY Mouse position at drag begin (for deadzone)
bool dragActive True once mouse moved past deadzone
int32_t resizeWindow, resizeEdge Active resize state
int32_t scrollWindow, scrollOrient, scrollDragOff Active scroll drag state</pre>
<h3>MenuT / MenuItemT / MenuBarT</h3>
<p>Menu system types. Fixed-size label buffers (MAX_MENU_LABEL = 32). Cascading submenus supported via MenuItemT.subMenu pointer.</p>
<pre> Field Description
----- -----------
MenuItemT.label Item text (supports &amp; accelerator markers)
MenuItemT.id Application-defined command ID
MenuItemT.type MenuItemNormalE, MenuItemCheckE, or MenuItemRadioE
MenuItemT.separator true = horizontal divider line
MenuItemT.enabled, checked Item state
MenuItemT.accelKey Lowercase accelerator character (0 = none)
MenuItemT.subMenu Child menu for cascading (NULL if leaf)
MenuT.label Menu bar label (e.g. &quot;File&quot;)
MenuT.items Dynamic array of MenuItemT
MenuT.itemCount, itemCap Current count and allocated capacity
MenuT.barX, barW Computed position/width on the menu bar
MenuT.accelKey Lowercase accelerator character (0 = none)
MenuBarT.menus Dynamic array of MenuT
MenuBarT.menuCount, menuCap Current count and allocated capacity
MenuBarT.activeIdx Open popup index (-1 = none)
MenuBarT.positionsDirty True when barX/barW need recomputation</pre>
<h3>ScrollbarT</h3>
<p>Window-level scrollbar state. Managed by the WM layer, drawn after content.</p>
<pre> Field Description
----- -----------
ScrollbarOrientE orient ScrollbarVerticalE or ScrollbarHorizontalE
int32_t min, max Scroll range
int32_t value Current position
int32_t pageSize Visible portion (for proportional thumb sizing)
int32_t x, y, length Computed screen position and track length</pre>
<h3>AccelTableT / AccelEntryT</h3>
<p>Per-window keyboard accelerator table. Entries are matched against keystrokes in the event loop and fire onMenu(cmdId) on match.</p>
<pre> Field Description
----- -----------
AccelEntryT.key ASCII character or KEY_Fxx constant
AccelEntryT.modifiers Bitmask of ACCEL_CTRL, ACCEL_SHIFT, ACCEL_ALT
AccelEntryT.cmdId Command ID passed to onMenu
AccelEntryT.normKey Pre-normalized key (uppercased) for fast matching
AccelEntryT.normMods Pre-masked modifiers (CTRL|ALT only) for fast matching
AccelTableT.entries Dynamic array of AccelEntryT
AccelTableT.count, cap Current count and allocated capacity</pre>
<h3>VideoModeInfoT</h3>
<p>Describes an available video mode (enumerated at init).</p>
<pre> Field Description
----- -----------
int32_t w, h Resolution
int32_t bpp Bits per pixel</pre>
<h3>CursorT</h3>
<p>Software-rendered 16x16 cursor using AND/XOR mask encoding.</p>
<pre> Field Description
----- -----------
int32_t width, height Cursor dimensions (always 16x16)
int32_t hotX, hotY Hot spot coordinates
const uint16_t *andMask AND mask (0 = draw pixel, 1 = transparent)
const uint16_t *xorData XOR data (0 = black, 1 = white where AND = 0)</pre>
<h2>Bevel Convenience Macros</h2>
<pre> Macro Description
----- -----------
BEVEL_RAISED(cs, bw) Raised bevel style from ColorSchemeT ptr and border width
BEVEL_SUNKEN(cs, face, bw) Sunken bevel style with explicit face color
BEVEL_TROUGH(cs) 1px sunken trough (for scrollbar tracks)
BEVEL_SB_BUTTON(cs) 1px raised scrollbar button</pre>
<h2>Chrome Constants</h2>
<pre> Define Value Description
------ ----- -----------
CHROME_BORDER_WIDTH 4 Outer frame border width
CHROME_TITLE_HEIGHT 20 Title bar height
CHROME_TITLE_PAD 4 Title text padding
CHROME_INNER_BORDER 2 Inner chrome border
CHROME_MENU_HEIGHT 20 Menu bar height
CHROME_TOTAL_TOP 26 Total inset from top of frame to content
CHROME_TOTAL_SIDE 6 Total inset from side of frame to content
CHROME_TOTAL_BOTTOM 6 Total inset from bottom of frame to content
CHROME_CLOSE_BTN_SIZE 16 Close button gadget size</pre>
<h2>Hit Test Constants</h2>
<pre> Define Value Description
------ ----- -----------
HIT_CONTENT 0 Content area
HIT_TITLE 1 Title bar
HIT_CLOSE 2 Close gadget
HIT_RESIZE 3 Resize border
HIT_MENU 4 Menu bar
HIT_VSCROLL 5 Vertical scrollbar
HIT_HSCROLL 6 Horizontal scrollbar
HIT_MINIMIZE 7 Minimize gadget
HIT_MAXIMIZE 8 Maximize gadget
HIT_NONE -1 No window hit (desktop)</pre>
<h2>Mouse Button Flags</h2>
<pre> Define Value Description
------ ----- -----------
MOUSE_LEFT 1 Left mouse button
MOUSE_RIGHT 2 Right mouse button
MOUSE_MIDDLE 4 Middle mouse button</pre>
<h2>Accelerator Modifier Flags</h2>
<pre> Define Value Description
------ ----- -----------
ACCEL_SHIFT 0x03 Shift key (matches BIOS shift state bits)
ACCEL_CTRL 0x04 Ctrl key
ACCEL_ALT 0x08 Alt key</pre>
<h2>Extended Key Codes</h2>
<pre> Define Description
------ -----------
KEY_F1 .. KEY_F12 Function keys (scancode | 0x100)
KEY_INSERT Insert key
KEY_DELETE Delete key
KEY_HOME Home key
KEY_END End key
KEY_PGUP Page Up key
KEY_PGDN Page Down key</pre>
<h2>Resize Edge Flags</h2>
<pre> Define Value Description
------ ----- -----------
RESIZE_NONE 0 No resize edge
RESIZE_LEFT 1 Left edge
RESIZE_RIGHT 2 Right edge
RESIZE_TOP 4 Top edge
RESIZE_BOTTOM 8 Bottom edge (combinable via OR for corners)</pre>
<h2>Utility Macros</h2>
<pre> Macro Description
----- -----------
DVX_MIN(a, b) Return the smaller of two values
DVX_MAX(a, b) Return the larger of two values</pre>
</div>
<div class="topic" id="api.cursor">
<h1>dvxCur.h -- Cursor Definitions</h1>
<p>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. The AND mask selects transparency (1 = transparent, 0 = opaque) and the XOR data selects black vs. white for opaque pixels.</p>
<h2>Cursor Shape IDs</h2>
<pre> Define Value Description
------ ----- -----------
CURSOR_ARROW 0 Standard arrow (hot spot at tip)
CURSOR_RESIZE_H 1 Horizontal resize (left/right arrows)
CURSOR_RESIZE_V 2 Vertical resize (up/down arrows)
CURSOR_RESIZE_DIAG_NWSE 3 NW-SE diagonal resize
CURSOR_RESIZE_DIAG_NESW 4 NE-SW diagonal resize
CURSOR_BUSY 5 Hourglass (wait)
CURSOR_CROSSHAIR 6 Crosshair for placement
CURSOR_COUNT 7 Total number of cursor shapes</pre>
<h2>Data</h2>
<h3>dvxCursors[CURSOR_COUNT]</h3>
<p>Static const array of CursorT structs, indexed by CURSOR_xxx constants. Each entry includes the AND mask, XOR data (both as 16-element uint16_t arrays), dimensions (16x16), and hot spot coordinates.</p>
<h3>dvxCursor</h3>
<p>Legacy alias for backward compatibility with code that predates multi-cursor support. Equivalent to dvxCursors[CURSOR_ARROW].</p>
</div>
<div class="topic" id="api.font">
<h1>dvxFont.h -- Embedded Bitmap Font Data</h1>
<p>Raw glyph bitmaps for the standard 8x16 VGA ROM font covering the full IBM Code Page 437 character set (256 glyphs). Compiled in as a static const array, avoiding a real-mode INT 10h call at startup.</p>
<p>Glyph format: 1 bit per pixel, 8 pixels wide, MSB = leftmost pixel. Each glyph occupies 16 consecutive bytes (one byte per scanline). The 8-pixel width means per-scanline rendering never needs bit shifting across byte boundaries.</p>
<p>CP437 covers:</p>
<ul>
<li>0-31 -- Smiley, card suits, arrows, notes (classic extended ASCII glyphs)</li>
<li>32-126 -- Printable ASCII</li>
<li>127 -- House glyph</li>
<li>128-175 -- Accented Latin letters, currency, fractions</li>
<li>176-223 -- Box-drawing characters (essential for chrome gadgets)</li>
<li>224-254 -- Greek letters, math symbols, super/subscripts</li>
</ul>
<p>255 -- Non-breaking space</p>
<h2>Data</h2>
<h3>font8x16</h3>
<p>Static const uint8_t array of 256 * 16 = 4096 bytes containing the packed 1bpp glyph bitmaps, in ASCII code order.</p>
<h3>dvxFont8x16</h3>
<p>Static const BitmapFontT struct describing the 8x16 font, ready to pass to drawText/drawTextN/drawChar. Use this as the default font for all text rendering.</p>
<h2>Constants</h2>
<pre> Define Value Description
------ ----- -----------
FONT_CHAR_WIDTH 8 Fixed glyph width in pixels (defined in dvxTypes.h)</pre>
</div>
<div class="topic" id="api.palette">
<h1>dvxPal.h -- 256-Color Palette for 8-bit Mode</h1>
<p>Defines the 256-color VGA/VESA palette used in 8-bit video modes. Layout:</p>
<pre> Range Purpose
----- -------
0-215 6x6x6 color cube -- uniformly distributed RGB (6 levels per channel: 0, 51, 102, 153, 204, 255). Index = r*36 + g*6 + b.
216-231 16-step grey ramp for smooth gradients
232-239 Dedicated UI chrome colors (highlight, shadow, title bar, desktop)
240-255 Reserved (black)</pre>
<p>The cube layout enables O(1) color lookup: snapping an RGB triplet to the nearest cube vertex is integer division by 51. The grey ramp and chrome slots hold colors that need exact values not available in the cube.</p>
<h2>Chrome Color Indices</h2>
<pre> Define Value Description
------ ----- -----------
PAL_CHROME_HIGHLIGHT 232 White (bevel highlight)
PAL_CHROME_SHADOW 233 Dark grey (bevel shadow)
PAL_CHROME_ACTIVE_BG 234 Navy (focused title bar)
PAL_CHROME_INACTIVE_BG 235 Grey (unfocused title bar)
PAL_CHROME_DESKTOP 236 Steel blue (desktop)
PAL_CHROME_SELECTION 237 Navy (selection highlight)
PAL_CHROME_TEXT 238 Black (text)
PAL_CHROME_WHITE 239 Bright white</pre>
<h2>Inline Functions</h2>
<h3>dvxGeneratePalette</h3>
<pre><code>static inline void dvxGeneratePalette(uint8_t *pal);</code></pre>
<p>Populate a 768-byte (256 * 3) RGB buffer with the default DVX 8-bit palette. Called once at init in 8-bit mode to program the DAC.</p>
<pre> Parameter Description
--------- -----------
pal Output RGB buffer (768 bytes)</pre>
<h3>dvxNearestPalEntry</h3>
<pre><code>static inline uint8_t dvxNearestPalEntry(const uint8_t *pal, uint8_t r, uint8_t g, uint8_t b);</code></pre>
<p>Find the nearest palette entry for an RGB color using minimum Euclidean distance. Two-phase: snap to color cube vertex (O(1)), then scan grey ramp and chrome entries (216-239) for a closer match. Called by packColor() in 8-bit mode.</p>
<pre> Parameter Description
--------- -----------
pal Active 768-byte RGB palette
r, g, b Color components (0-255)</pre>
<p>Returns: Palette index (0-239) of the nearest match.</p>
</div>
<div class="topic" id="api.video">
<h1>dvxVideo.h -- Layer 1: VESA VBE Video Backend</h1>
<p>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>
<h2>videoInit</h2>
<pre><code>int32_t videoInit(DisplayT *d, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context to initialize
requestedW/H Desired screen resolution
preferredBpp Preferred bits per pixel (8, 15, 16, or 32)</pre>
<p>Returns: 0 on success, negative on failure.</p>
<h2>videoShutdown</h2>
<pre><code>void videoShutdown(DisplayT *d);</code></pre>
<p>Restore VGA text mode (mode 3), unmap the LFB, and free the backbuffer. Safe to call even if videoInit() failed.</p>
<pre> Parameter Description
--------- -----------
d Display context to shut down</pre>
<h2>packColor</h2>
<pre><code>uint32_t packColor(const DisplayT *d, uint8_t r, uint8_t g, uint8_t b);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context (provides pixel format)
r, g, b Color components (0-255)</pre>
<p>Returns: Native pixel value suitable for direct framebuffer write.</p>
<h2>unpackColor</h2>
<pre><code>void unpackColor(const DisplayT *d, uint32_t color, uint8_t *r, uint8_t *g, uint8_t *b);</code></pre>
<p>Reverse of packColor -- decode a native pixel value to 8-bit RGB components. For direct-color modes, reverses the shift/mask arithmetic. For 8-bit mode, looks up the palette entry at the given index.</p>
<pre> Parameter Description
--------- -----------
d Display context
color Packed native pixel value
r, g, b Output: color components (0-255)</pre>
<h2>setClipRect</h2>
<pre><code>void setClipRect(DisplayT *d, int32_t x, int32_t y, int32_t w, int32_t h);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
x, y, w, h Clip rectangle in screen coordinates</pre>
<h2>resetClipRect</h2>
<pre><code>void resetClipRect(DisplayT *d);</code></pre>
<p>Reset the clip rectangle to the full display dimensions.</p>
<pre> Parameter Description
--------- -----------
d Display context</pre>
</div>
<div class="topic" id="api.draw">
<h1>dvxDraw.h -- Layer 2: Drawing Primitives</h1>
<p>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>
<h2>drawInit</h2>
<pre><code>void drawInit(BlitOpsT *ops, const DisplayT *d);</code></pre>
<p>Populate a BlitOpsT with the correct span functions for the display's pixel depth. Must be called once after videoInit().</p>
<pre> Parameter Description
--------- -----------
ops BlitOpsT to populate
d Initialized display context</pre>
<h2>rectFill</h2>
<pre><code>void rectFill(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);</code></pre>
<p>Fill a rectangle with a solid color. Clips to the display clip rect. Workhorse for backgrounds, window fills, and clear operations.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
x, y, w, h Rectangle to fill
color Packed pixel color</pre>
<h2>rectCopy</h2>
<pre><code>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);</code></pre>
<p>Copy a rectangle from an arbitrary source buffer into the backbuffer. Used to blit per-window content buffers during compositing.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
dstX, dstY Destination position in backbuffer
srcBuf Source pixel buffer
srcPitch Source buffer bytes per row
srcX, srcY Origin within source buffer
w, h Rectangle dimensions to copy</pre>
<h2>rectCopyGrayscale</h2>
<pre><code>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);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
dstX, dstY Destination position
srcBuf, srcPitch Source buffer and pitch
srcX, srcY Source origin
w, h Rectangle dimensions</pre>
<h2>rectCopyTransparent</h2>
<pre><code>void rectCopyTransparent(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, uint32_t keyColor);</code></pre>
<p>Copy with color-key transparency. Pixels matching keyColor are skipped, letting the destination show through. Used to draw image buttons and icons with transparent backgrounds.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
dstX, dstY Destination position
srcBuf, srcPitch Source buffer and pitch
srcX, srcY Source origin
w, h Rectangle dimensions
keyColor Packed color treated as transparent</pre>
<h2>drawBevel</h2>
<pre><code>void drawBevel(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, const BevelStyleT *style);</code></pre>
<p>Draw a beveled frame. Top/left edges in highlight color, bottom/right in shadow. Interior filled with face color if non-zero.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
x, y, w, h Outer bevel rectangle
style Bevel colors and width</pre>
<h2>drawChar</h2>
<pre><code>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);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
font Bitmap font
x, y Character position
ch Character to draw
fg, bg Foreground and background packed colors
opaque true = fill background, false = transparent</pre>
<p>Returns: Advance width (always charWidth).</p>
<h2>drawText</h2>
<pre><code>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);</code></pre>
<p>Draw a null-terminated string. Calls drawChar per character.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
font Bitmap font
x, y Start position
text Null-terminated string
fg, bg Foreground and background packed colors
opaque true = fill background, false = transparent</pre>
<h2>drawTextN</h2>
<pre><code>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);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
font Bitmap font
x, y Start position
text Character buffer (not required to be null-terminated)
count Number of characters to render
fg, bg Foreground and background packed colors
opaque true = fill background, false = transparent</pre>
<h2>textWidth</h2>
<pre><code>int32_t textWidth(const BitmapFontT *font, const char *text);</code></pre>
<p>Return the pixel width of a null-terminated string (strlen(text) * charWidth).</p>
<pre> Parameter Description
--------- -----------
font Bitmap font
text Null-terminated string</pre>
<p>Returns: Width in pixels.</p>
<h2>accelParse</h2>
<pre><code>char accelParse(const char *text);</code></pre>
<p>Scan text for an &amp; prefix and return the following character as a lowercase accelerator key. &quot;&amp;File&quot; returns 'f', &quot;E&amp;xit&quot; returns 'x'.</p>
<pre> Parameter Description
--------- -----------
text Text with optional &amp; accelerator marker</pre>
<p>Returns: Lowercase accelerator character, or 0 if none.</p>
<h2>drawTextAccel</h2>
<pre><code>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);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
font Bitmap font
x, y Start position
text Text with &amp; markers
fg, bg Foreground and background packed colors
opaque true = fill background, false = transparent</pre>
<h2>textWidthAccel</h2>
<pre><code>int32_t textWidthAccel(const BitmapFontT *font, const char *text);</code></pre>
<p>Measure text width excluding &amp; markers (so &quot;&amp;File&quot; measures as 4 chars).</p>
<pre> Parameter Description
--------- -----------
font Bitmap font
text Text with optional &amp; markers</pre>
<p>Returns: Width in pixels.</p>
<h2>drawMaskedBitmap</h2>
<pre><code>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);</code></pre>
<p>Draw a 1-bit AND/XOR masked bitmap. Used for software-rendered mouse cursors.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
x, y Screen position
w, h Bitmap dimensions
andMask AND transparency mask (one uint16_t per row)
xorData XOR color data
fgColor, bgColor Cursor foreground and background packed colors</pre>
<h2>drawTermRow</h2>
<pre><code>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);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
font Bitmap font
x, y Row start position
cols Number of columns
lineData Packed ch/attr byte pairs (2 bytes per cell)
palette 16-entry packed color palette
blinkVisible false = hide blinking characters
cursorCol Column for inverted text cursor (-1 = none)</pre>
<h2>drawFocusRect</h2>
<pre><code>void drawFocusRect(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);</code></pre>
<p>Draw a 1px dotted rectangle (alternating pixels). Used for keyboard focus indicators, matching the Windows 3.x focus rectangle convention.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
x, y, w, h Focus rectangle bounds
color Dot color (packed)</pre>
<h2>drawHLine</h2>
<pre><code>void drawHLine(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t w, uint32_t color);</code></pre>
<p>Draw a horizontal line (1px tall).</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
x, y Start position
w Width in pixels
color Packed pixel color</pre>
<h2>drawVLine</h2>
<pre><code>void drawVLine(DisplayT *d, const BlitOpsT *ops, int32_t x, int32_t y, int32_t h, uint32_t color);</code></pre>
<p>Draw a vertical line (1px wide).</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
x, y Start position
h Height in pixels
color Packed pixel color</pre>
</div>
<div class="topic" id="api.comp">
<h1>dvxComp.h -- Layer 3: Dirty Rectangle Compositor</h1>
<p>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>
<h2>dirtyListInit</h2>
<pre><code>void dirtyListInit(DirtyListT *dl);</code></pre>
<p>Zero the dirty rect count. Called at the start of each frame.</p>
<pre> Parameter Description
--------- -----------
dl Dirty list to initialize</pre>
<h2>dirtyListAdd</h2>
<pre><code>void dirtyListAdd(DirtyListT *dl, int32_t x, int32_t y, int32_t w, int32_t h);</code></pre>
<p>Enqueue a dirty rectangle. Grows dynamically; triggers merge at a soft capacity limit.</p>
<pre> Parameter Description
--------- -----------
dl Dirty list
x, y, w, h Dirty rectangle in screen coordinates</pre>
<h2>dirtyListMerge</h2>
<pre><code>void dirtyListMerge(DirtyListT *dl);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
dl Dirty list to merge</pre>
<h2>dirtyListClear</h2>
<pre><code>void dirtyListClear(DirtyListT *dl);</code></pre>
<p>Reset the dirty list to empty (sets count to 0).</p>
<pre> Parameter Description
--------- -----------
dl Dirty list to clear</pre>
<h2>flushRect</h2>
<pre><code>void flushRect(DisplayT *d, const RectT *r);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
r Rectangle to flush</pre>
<h2>rectIntersect</h2>
<pre><code>bool rectIntersect(const RectT *a, const RectT *b, RectT *result);</code></pre>
<p>Compute the intersection of two rectangles.</p>
<pre> Parameter Description
--------- -----------
a, b Input rectangles
result Output: intersection rectangle (valid only when return is true)</pre>
<p>Returns: true if the rectangles overlap, false if disjoint.</p>
<h2>rectIsEmpty</h2>
<pre><code>bool rectIsEmpty(const RectT *r);</code></pre>
<p>Test whether a rectangle has zero or negative area.</p>
<pre> Parameter Description
--------- -----------
r Rectangle to test</pre>
<p>Returns: true if w &lt;= 0 or h &lt;= 0.</p>
</div>
<div class="topic" id="api.wm">
<h1>dvxWm.h -- Layer 4: Window Manager</h1>
<p>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>
<h2>Initialization</h2>
<h3>wmInit</h3>
<pre><code>void wmInit(WindowStackT *stack);</code></pre>
<p>Zero the window stack. Must be called before any other WM function.</p>
<pre> Parameter Description
--------- -----------
stack Window stack to initialize</pre>
<h2>Window Lifecycle</h2>
<h3>wmCreateWindow</h3>
<pre><code>WindowT *wmCreateWindow(WindowStackT *stack, DisplayT *d, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, bool resizable);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
stack Window stack
d Display context
title Window title text
x, y Initial position
w, h Initial outer frame dimensions
resizable true = allow user resize</pre>
<p>Returns: Pointer to new WindowT, or NULL on failure.</p>
<h3>wmDestroyWindow</h3>
<pre><code>void wmDestroyWindow(WindowStackT *stack, WindowT *win);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
stack Window stack
win Window to destroy</pre>
<h2>Z-Order and Focus</h2>
<h3>wmRaiseWindow</h3>
<pre><code>void wmRaiseWindow(WindowStackT *stack, DirtyListT *dl, int32_t idx);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list for repaint marking
idx Stack index of window to raise</pre>
<h3>wmSetFocus</h3>
<pre><code>void wmSetFocus(WindowStackT *stack, DirtyListT *dl, int32_t idx);</code></pre>
<p>Transfer keyboard focus to the window at stack index idx. Unfocuses the previously focused window and dirties both title bars.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
idx Stack index of window to focus</pre>
<h2>Geometry</h2>
<h3>wmUpdateContentRect</h3>
<pre><code>void wmUpdateContentRect(WindowT *win);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
win Window to update</pre>
<h3>wmReallocContentBuf</h3>
<pre><code>int32_t wmReallocContentBuf(WindowT *win, const DisplayT *d);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
win Window to reallocate
d Display context (for bytes-per-pixel)</pre>
<p>Returns: 0 on success, -1 on allocation failure.</p>
<h3>wmMinWindowSize</h3>
<pre><code>void wmMinWindowSize(const WindowT *win, int32_t *minW, int32_t *minH);</code></pre>
<p>Get the minimum window size. Accounts for chrome, gadgets, and menu bar.</p>
<pre> Parameter Description
--------- -----------
win Window
minW, minH Output: minimum width and height</pre>
<h2>Menu Bar</h2>
<h3>wmAddMenuBar</h3>
<pre><code>MenuBarT *wmAddMenuBar(WindowT *win);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
win Window to add menu bar to</pre>
<p>Returns: Pointer to the new MenuBarT.</p>
<h3>wmDestroyMenuBar</h3>
<pre><code>void wmDestroyMenuBar(WindowT *win);</code></pre>
<p>Free the menu bar and reclaim the content area.</p>
<pre> Parameter Description
--------- -----------
win Window to remove menu bar from</pre>
<h3>wmAddMenu</h3>
<pre><code>MenuT *wmAddMenu(MenuBarT *bar, const char *label);</code></pre>
<p>Append a dropdown menu to the menu bar. The label supports &amp; accelerator markers (e.g. &quot;&amp;File&quot;).</p>
<pre> Parameter Description
--------- -----------
bar Menu bar
label Menu label text</pre>
<p>Returns: Pointer to the new MenuT to populate with items.</p>
<h3>wmAddMenuItem</h3>
<pre><code>void wmAddMenuItem(MenuT *menu, const char *label, int32_t id);</code></pre>
<p>Append a clickable item to a menu. The id is passed to the window's onMenu callback when selected.</p>
<pre> Parameter Description
--------- -----------
menu Menu to append to
label Item label (supports &amp; markers)
id Application-defined command ID</pre>
<h3>wmAddMenuCheckItem</h3>
<pre><code>void wmAddMenuCheckItem(MenuT *menu, const char *label, int32_t id, bool checked);</code></pre>
<p>Add a checkbox-style menu item. Check state toggles on click; rendered with a checkmark glyph.</p>
<pre> Parameter Description
--------- -----------
menu Menu to append to
label Item label
id Command ID
checked Initial checked state</pre>
<h3>wmAddMenuRadioItem</h3>
<pre><code>void wmAddMenuRadioItem(MenuT *menu, const char *label, int32_t id, bool checked);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
menu Menu to append to
label Item label
id Command ID
checked Initial checked state</pre>
<h3>wmAddMenuSeparator</h3>
<pre><code>void wmAddMenuSeparator(MenuT *menu);</code></pre>
<p>Insert a horizontal separator line. Separators are not interactive.</p>
<pre> Parameter Description
--------- -----------
menu Menu to append separator to</pre>
<h3>wmRemoveMenuItem</h3>
<pre><code>bool wmRemoveMenuItem(MenuT *menu, int32_t id);</code></pre>
<p>Remove a menu item by command ID. Searches the menu's items array and shifts remaining items down to close the gap.</p>
<pre> Parameter Description
--------- -----------
menu Menu to remove item from
id Command ID to remove</pre>
<p>Returns: true if a matching item was found and removed.</p>
<h3>wmClearMenuItems</h3>
<pre><code>void wmClearMenuItems(MenuT *menu);</code></pre>
<p>Remove all items from a menu while preserving the menu itself on the menu bar. Use when rebuilding a menu's contents dynamically (e.g. a recent-files submenu).</p>
<pre> Parameter Description
--------- -----------
menu Menu to empty</pre>
<h3>wmMenuItemIsChecked</h3>
<pre><code>bool wmMenuItemIsChecked(MenuBarT *bar, int32_t id);</code></pre>
<p>Query the checked state of a menu item by command ID. Searches all menus in the bar.</p>
<pre> Parameter Description
--------- -----------
bar Menu bar
id Command ID to query</pre>
<p>Returns: true if checked.</p>
<h3>wmMenuItemSetChecked</h3>
<pre><code>void wmMenuItemSetChecked(MenuBarT *bar, int32_t id, bool checked);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
bar Menu bar
id Command ID
checked New checked state</pre>
<h3>wmMenuItemSetEnabled</h3>
<pre><code>void wmMenuItemSetEnabled(MenuBarT *bar, int32_t id, bool enabled);</code></pre>
<p>Enable or disable a menu item by command ID.</p>
<pre> Parameter Description
--------- -----------
bar Menu bar
id Command ID
enabled true = enabled, false = grayed out</pre>
<h3>wmAddSubMenu</h3>
<pre><code>MenuT *wmAddSubMenu(MenuT *parentMenu, const char *label);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
parentMenu Parent menu to attach submenu to
label Submenu label text</pre>
<p>Returns: Pointer to the child MenuT, or NULL on allocation failure.</p>
<h3>wmCreateMenu</h3>
<pre><code>MenuT *wmCreateMenu(void);</code></pre>
<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>Returns: Pointer to the new MenuT.</p>
<h3>wmFreeMenu</h3>
<pre><code>void wmFreeMenu(MenuT *menu);</code></pre>
<p>Free a standalone menu allocated with wmCreateMenu(). Also frees any heap-allocated submenu children recursively.</p>
<pre> Parameter Description
--------- -----------
menu Menu to free</pre>
<h2>Scrollbars</h2>
<h3>wmAddVScrollbar</h3>
<pre><code>ScrollbarT *wmAddVScrollbar(WindowT *win, int32_t min, int32_t max, int32_t pageSize);</code></pre>
<p>Attach a vertical scrollbar to the right edge of the window's content area. Shrinks contentW by SCROLLBAR_WIDTH pixels.</p>
<pre> Parameter Description
--------- -----------
win Window
min, max Scroll value range
pageSize Visible portion (controls thumb size)</pre>
<p>Returns: Pointer to the new ScrollbarT.</p>
<h3>wmAddHScrollbar</h3>
<pre><code>ScrollbarT *wmAddHScrollbar(WindowT *win, int32_t min, int32_t max, int32_t pageSize);</code></pre>
<p>Attach a horizontal scrollbar to the bottom edge. Shrinks contentH by SCROLLBAR_WIDTH pixels.</p>
<pre> Parameter Description
--------- -----------
win Window
min, max Scroll value range
pageSize Visible portion</pre>
<p>Returns: Pointer to the new ScrollbarT.</p>
<h2>Drawing</h2>
<h3>wmDrawChrome</h3>
<pre><code>void wmDrawChrome(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors, WindowT *win, const RectT *clipTo);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
font Bitmap font for title text
colors Color scheme
win Window to draw chrome for
clipTo Dirty rectangle to clip drawing to</pre>
<h3>wmDrawContent</h3>
<pre><code>void wmDrawContent(DisplayT *d, const BlitOpsT *ops, WindowT *win, const RectT *clipTo);</code></pre>
<p>Blit the window's content backbuffer into the display backbuffer, clipped to the dirty rect. Pure copy operation (no drawing).</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
win Window
clipTo Dirty rectangle</pre>
<h3>wmDrawScrollbars</h3>
<pre><code>void wmDrawScrollbars(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, WindowT *win, const RectT *clipTo);</code></pre>
<p>Draw scrollbars (track, arrows, proportional thumb) for a window. Drawn after content so scrollbars overlay the content area edge.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
colors Color scheme
win Window
clipTo Dirty rectangle</pre>
<h3>wmDrawMinimizedIcons</h3>
<pre><code>void wmDrawMinimizedIcons(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, const WindowStackT *stack, const RectT *clipTo);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
colors Color scheme
stack Window stack
clipTo Dirty rectangle</pre>
<h3>wmDrawVScrollbarAt</h3>
<pre><code>void wmDrawVScrollbarAt(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, int32_t x, int32_t y, int32_t h, int32_t scrollPos, int32_t visibleItems, int32_t totalItems);</code></pre>
<p>Draw a standalone vertical scrollbar at the given screen coordinates, without a ScrollbarT struct. Used by popup lists (dropdown, combobox) that need a scrollbar inline within a popup overlay. Thumb size and position are computed from scrollPos / visibleItems / totalItems.</p>
<pre> Parameter Description
--------- -----------
d Display context
ops Blit operations vtable
colors Color scheme
x, y Screen position (top of scrollbar)
h Track height in pixels
scrollPos Current top visible item index
visibleItems Visible item count (for thumb size)
totalItems Total item count</pre>
<h2>Hit Testing</h2>
<h3>wmHitTest</h3>
<pre><code>int32_t wmHitTest(const WindowStackT *stack, int32_t mx, int32_t my, int32_t *hitPart);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
stack Window stack
mx, my Screen coordinates
hitPart Output: HIT_CONTENT, HIT_TITLE, HIT_CLOSE, etc.</pre>
<p>Returns: Stack index of hit window, or -1 for desktop.</p>
<h3>wmResizeEdgeHit</h3>
<pre><code>int32_t wmResizeEdgeHit(const WindowT *win, int32_t mx, int32_t my);</code></pre>
<p>Determine which edge(s) of a window's border zone are targeted for resize.</p>
<pre> Parameter Description
--------- -----------
win Window
mx, my Screen coordinates</pre>
<p>Returns: Bitmask of RESIZE_LEFT / RESIZE_RIGHT / RESIZE_TOP / RESIZE_BOTTOM.</p>
<h3>wmMinimizedIconHit</h3>
<pre><code>int32_t wmMinimizedIconHit(const WindowStackT *stack, const DisplayT *d, int32_t mx, int32_t my);</code></pre>
<p>Hit-test minimized icons at the bottom of the screen.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
d Display context
mx, my Screen coordinates</pre>
<p>Returns: Stack index of the minimized window, or -1.</p>
<h2>Drag and Resize</h2>
<h3>wmDragBegin</h3>
<pre><code>void wmDragBegin(WindowStackT *stack, int32_t idx, int32_t mouseX, int32_t mouseY);</code></pre>
<p>Begin a window drag operation. Records the mouse offset from the window origin.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
idx Stack index of window to drag
mouseX/Y Current mouse position</pre>
<h3>wmDragMove</h3>
<pre><code>void wmDragMove(WindowStackT *stack, DirtyListT *dl, int32_t mouseX, int32_t mouseY, int32_t screenW, int32_t screenH);</code></pre>
<p>Update window position during an active drag. Dirties both old and new positions.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
mouseX/Y Current mouse position
screenW/H Screen dimensions (for clamping)</pre>
<h3>wmDragEnd</h3>
<pre><code>void wmDragEnd(WindowStackT *stack);</code></pre>
<p>End the current drag operation. Clears dragWindow state.</p>
<pre> Parameter Description
--------- -----------
stack Window stack</pre>
<h3>wmResizeBegin</h3>
<pre><code>void wmResizeBegin(WindowStackT *stack, int32_t idx, int32_t edge, int32_t mouseX, int32_t mouseY);</code></pre>
<p>Begin a window resize operation. Records which edge(s) are being dragged.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
idx Stack index
edge Bitmask of RESIZE_xxx flags
mouseX/Y Current mouse position</pre>
<h3>wmResizeMove</h3>
<pre><code>void wmResizeMove(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, int32_t *mouseX, int32_t *mouseY);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
d Display context
mouseX/Y In/out: mouse position (clamped on return)</pre>
<h3>wmResizeEnd</h3>
<pre><code>void wmResizeEnd(WindowStackT *stack);</code></pre>
<p>End the current resize operation. Clears resizeWindow state.</p>
<pre> Parameter Description
--------- -----------
stack Window stack</pre>
<h2>Scrollbar Interaction</h2>
<h3>wmScrollbarClick</h3>
<pre><code>void wmScrollbarClick(WindowStackT *stack, DirtyListT *dl, int32_t idx, int32_t orient, int32_t mx, int32_t my);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
idx Stack index of window
orient SCROLL_VERTICAL or SCROLL_HORIZONTAL
mx, my Click screen coordinates</pre>
<h3>wmScrollbarDrag</h3>
<pre><code>void wmScrollbarDrag(WindowStackT *stack, DirtyListT *dl, int32_t mx, int32_t my);</code></pre>
<p>Update the scroll value during an active thumb drag. Maps mouse position along the track to a proportional scroll value.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
mx, my Current mouse position</pre>
<h3>wmScrollbarEnd</h3>
<pre><code>void wmScrollbarEnd(WindowStackT *stack);</code></pre>
<p>End an active scrollbar thumb drag.</p>
<pre> Parameter Description
--------- -----------
stack Window stack</pre>
<h2>Minimize / Maximize / Restore</h2>
<h3>wmMaximize</h3>
<pre><code>void wmMaximize(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, WindowT *win);</code></pre>
<p>Maximize a window. Saves current geometry, then expands to screen or maxW/maxH bounds.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
d Display context
win Window to maximize</pre>
<h3>wmMinimize</h3>
<pre><code>void wmMinimize(WindowStackT *stack, DirtyListT *dl, WindowT *win);</code></pre>
<p>Minimize a window. Hides the window and shows an icon at the bottom of the screen.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
win Window to minimize</pre>
<h3>wmRestore</h3>
<pre><code>void wmRestore(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, WindowT *win);</code></pre>
<p>Restore a maximized window to its pre-maximize geometry.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
d Display context
win Maximized window to restore</pre>
<h3>wmRestoreMinimized</h3>
<pre><code>void wmRestoreMinimized(WindowStackT *stack, DirtyListT *dl, const DisplayT *d, WindowT *win);</code></pre>
<p>Restore a minimized window (show it again and remove the icon).</p>
<pre> Parameter Description
--------- -----------
stack Window stack
dl Dirty list
d Display context
win Minimized window to restore</pre>
<h2>Minimized Icon Layout</h2>
<h3>wmMinimizedIconPos</h3>
<pre><code>void wmMinimizedIconPos(const DisplayT *d, int32_t index, int32_t *x, int32_t *y);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
d Display context
index Ordinal index of the minimized icon
x, y Output: screen position</pre>
<h3>wmMinimizedIconRect</h3>
<pre><code>void wmMinimizedIconRect(const WindowStackT *stack, const DisplayT *d, int32_t *y, int32_t *h);</code></pre>
<p>Compute the screen rect covering all minimized icon rows. Used to dirty the icon area when windows are minimized or restored.</p>
<pre> Parameter Description
--------- -----------
stack Window stack
d Display context
y, h Output: vertical extent of icon area</pre>
<h2>Miscellaneous</h2>
<h3>wmSetTitle</h3>
<pre><code>void wmSetTitle(WindowT *win, DirtyListT *dl, const char *title);</code></pre>
<p>Set the window title and dirty the title bar for repaint.</p>
<pre> Parameter Description
--------- -----------
win Window
dl Dirty list
title New title text</pre>
<h3>wmSetIcon</h3>
<pre><code>int32_t wmSetIcon(WindowT *win, const char *path, const DisplayT *d);</code></pre>
<p>Load an icon image for a window from a file. Converts to display pixel format.</p>
<pre> Parameter Description
--------- -----------
win Window
path Image file path
d Display context</pre>
<p>Returns: 0 on success, -1 on failure.</p>
</div>
<div class="topic" id="api.app">
<h1>dvxApp.h -- Layer 5: Application API</h1>
<p>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>
<h2>AppContextT</h2>
<p>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.</p>
<h2>Initialization and Shutdown</h2>
<h3>dvxInit</h3>
<pre><code>int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
ctx Application context to initialize
requestedW/H Desired screen resolution
preferredBpp Preferred bits per pixel</pre>
<p>Returns: 0 on success, negative on failure.</p>
<h3>dvxShutdown</h3>
<pre><code>void dvxShutdown(AppContextT *ctx);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h3>dvxChangeVideoMode</h3>
<pre><code>int32_t dvxChangeVideoMode(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
ctx Application context
requestedW/H New resolution
preferredBpp New bits per pixel</pre>
<p>Returns: 0 on success, -1 on failure (old mode restored).</p>
<h2>Event Loop</h2>
<h3>dvxRun</h3>
<pre><code>void dvxRun(AppContextT *ctx);</code></pre>
<p>Enter the main event loop. Polls input, dispatches events, composites dirty regions, and yields on each iteration. Returns when ctx-&gt;running becomes false.</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h3>dvxUpdate</h3>
<pre><code>bool dvxUpdate(AppContextT *ctx);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<p>Returns: false when the GUI wants to exit.</p>
<h3>dvxQuit</h3>
<pre><code>void dvxQuit(AppContextT *ctx);</code></pre>
<p>Request exit from the main event loop (sets ctx-&gt;running = false).</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h2>Window Management</h2>
<h3>dvxCreateWindow</h3>
<pre><code>WindowT *dvxCreateWindow(AppContextT *ctx, const char *title, int32_t x, int32_t y, int32_t w, int32_t h, bool resizable);</code></pre>
<p>Create a window at an explicit screen position. The window is raised to the top, focused, and its entire region is dirtied.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Window title
x, y Screen position
w, h Outer frame dimensions
resizable true = allow user resize</pre>
<p>Returns: Pointer to new WindowT.</p>
<h3>dvxCreateWindowCentered</h3>
<pre><code>WindowT *dvxCreateWindowCentered(AppContextT *ctx, const char *title, int32_t w, int32_t h, bool resizable);</code></pre>
<p>Convenience wrapper that centers the window on screen.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Window title
w, h Outer frame dimensions
resizable true = allow user resize</pre>
<p>Returns: Pointer to new WindowT.</p>
<h3>dvxDestroyWindow</h3>
<pre><code>void dvxDestroyWindow(AppContextT *ctx, WindowT *win);</code></pre>
<p>Destroy a window, free all its resources, and dirty its former region.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to destroy</pre>
<h3>dvxRaiseWindow</h3>
<pre><code>void dvxRaiseWindow(AppContextT *ctx, WindowT *win);</code></pre>
<p>Raise a window to the top of the Z-order and give it focus.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to raise</pre>
<h3>dvxFitWindow</h3>
<pre><code>void dvxFitWindow(AppContextT *ctx, WindowT *win);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to fit</pre>
<h3>dvxFitWindowW</h3>
<pre><code>void dvxFitWindowW(AppContextT *ctx, WindowT *win);</code></pre>
<p>Resize window width only to fit widget tree's minimum width (plus chrome).</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to fit</pre>
<h3>dvxFitWindowH</h3>
<pre><code>void dvxFitWindowH(AppContextT *ctx, WindowT *win);</code></pre>
<p>Resize window height only to fit widget tree's minimum height (plus chrome).</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to fit</pre>
<h3>dvxResizeWindow</h3>
<pre><code>void dvxResizeWindow(AppContextT *ctx, WindowT *win, int32_t newW, int32_t newH);</code></pre>
<p>Programmatically resize a window to the specified outer dimensions.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to resize
newW, newH New outer frame dimensions</pre>
<h3>dvxMinimizeWindow</h3>
<pre><code>void dvxMinimizeWindow(AppContextT *ctx, WindowT *win);</code></pre>
<p>Minimize a window (show as icon at bottom of screen).</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to minimize</pre>
<h3>dvxMaximizeWindow</h3>
<pre><code>void dvxMaximizeWindow(AppContextT *ctx, WindowT *win);</code></pre>
<p>Maximize a window (expand to fill screen or maxW/maxH).</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to maximize</pre>
<h3>dvxHideWindow</h3>
<pre><code>void dvxHideWindow(AppContextT *ctx, WindowT *win);</code></pre>
<p>Hide a window without destroying it. Marks the exposed region dirty.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to hide</pre>
<h3>dvxShowWindow</h3>
<pre><code>void dvxShowWindow(AppContextT *ctx, WindowT *win);</code></pre>
<p>Show a previously hidden window. Marks its region dirty for repaint.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to show</pre>
<h2>Invalidation</h2>
<h3>dvxInvalidateRect</h3>
<pre><code>void dvxInvalidateRect(AppContextT *ctx, WindowT *win, int32_t x, int32_t y, int32_t w, int32_t h);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window
x, y, w, h Dirty rectangle in content-relative coordinates</pre>
<h3>dvxInvalidateWindow</h3>
<pre><code>void dvxInvalidateWindow(AppContextT *ctx, WindowT *win);</code></pre>
<p>Mark the entire window content area as dirty.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to invalidate</pre>
<h2>Window Properties</h2>
<h3>dvxSetTitle</h3>
<pre><code>void dvxSetTitle(AppContextT *ctx, WindowT *win, const char *title);</code></pre>
<p>Set a window's title text and dirty the title bar.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window
title New title text</pre>
<h3>dvxSetWindowIcon</h3>
<pre><code>int32_t dvxSetWindowIcon(AppContextT *ctx, WindowT *win, const char *path);</code></pre>
<p>Load an icon for a window from an image file.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window
path Image file path</pre>
<p>Returns: 0 on success, -1 on failure.</p>
<h3>dvxSetBusy</h3>
<pre><code>void dvxSetBusy(AppContextT *ctx, bool busy);</code></pre>
<p>Set or clear busy state. While busy, the hourglass cursor is shown and input is blocked.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
busy true = show hourglass, false = normal</pre>
<h2>Accessors</h2>
<h3>dvxGetFont</h3>
<pre><code>const BitmapFontT *dvxGetFont(const AppContextT *ctx);</code></pre>
<p>Get a pointer to the default font.</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<p>Returns: Pointer to the active BitmapFontT.</p>
<h3>dvxGetColors</h3>
<pre><code>const ColorSchemeT *dvxGetColors(const AppContextT *ctx);</code></pre>
<p>Get a pointer to the current color scheme.</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<p>Returns: Pointer to the active ColorSchemeT.</p>
<h3>dvxGetDisplay</h3>
<pre><code>DisplayT *dvxGetDisplay(AppContextT *ctx);</code></pre>
<p>Get a pointer to the display context.</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<p>Returns: Pointer to the DisplayT.</p>
<h3>dvxGetBlitOps</h3>
<pre><code>const BlitOpsT *dvxGetBlitOps(const AppContextT *ctx);</code></pre>
<p>Get a pointer to the blit operations vtable.</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<p>Returns: Pointer to the active BlitOpsT.</p>
<h3>dvxGetVideoModes</h3>
<pre><code>const VideoModeInfoT *dvxGetVideoModes(const AppContextT *ctx, int32_t *count);</code></pre>
<p>Return the list of available video modes enumerated at init time.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
count Output: number of mode entries</pre>
<p>Returns: Pointer to the VideoModeInfoT array.</p>
<h2>Color Scheme</h2>
<h3>dvxSetColor</h3>
<pre><code>void dvxSetColor(AppContextT *ctx, ColorIdE id, uint8_t r, uint8_t g, uint8_t b);</code></pre>
<p>Set a single color by ID. Repacks to native pixel format and invalidates the entire screen.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
id Color ID (ColorIdE)
r, g, b RGB values (0-255)</pre>
<h3>dvxGetColor</h3>
<pre><code>void dvxGetColor(const AppContextT *ctx, ColorIdE id, uint8_t *r, uint8_t *g, uint8_t *b);</code></pre>
<p>Get a color's RGB values by ID.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
id Color ID (ColorIdE)
r, g, b Output: RGB values</pre>
<h3>dvxApplyColorScheme</h3>
<pre><code>void dvxApplyColorScheme(AppContextT *ctx);</code></pre>
<p>Apply all colors from ctx-&gt;colorRgb[] at once (repack + full repaint).</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h3>dvxResetColorScheme</h3>
<pre><code>void dvxResetColorScheme(AppContextT *ctx);</code></pre>
<p>Reset all colors to the built-in defaults and repaint.</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h3>dvxLoadTheme</h3>
<pre><code>bool dvxLoadTheme(AppContextT *ctx, const char *filename);</code></pre>
<p>Load a theme file (INI format with [colors] section) and apply it.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
filename Path to theme INI file</pre>
<p>Returns: true on success.</p>
<h3>dvxSaveTheme</h3>
<pre><code>bool dvxSaveTheme(const AppContextT *ctx, const char *filename);</code></pre>
<p>Save the current color scheme to a theme file.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
filename Output file path</pre>
<p>Returns: true on success.</p>
<h3>dvxColorName</h3>
<pre><code>const char *dvxColorName(ColorIdE id);</code></pre>
<p>Return the INI key name for a color ID (e.g. &quot;desktop&quot;, &quot;windowFace&quot;).</p>
<pre> Parameter Description
--------- -----------
id Color ID</pre>
<p>Returns: Static string.</p>
<h3>dvxColorLabel</h3>
<pre><code>const char *dvxColorLabel(ColorIdE id);</code></pre>
<p>Return a human-readable display label (e.g. &quot;Desktop&quot;, &quot;Cursor Color&quot;).</p>
<pre> Parameter Description
--------- -----------
id Color ID</pre>
<p>Returns: Static string.</p>
<h2>Wallpaper</h2>
<h3>dvxSetWallpaper</h3>
<pre><code>bool dvxSetWallpaper(AppContextT *ctx, const char *path);</code></pre>
<p>Load and apply a wallpaper image using the current wallpaperMode (stretch/tile/center). Pass NULL to clear the wallpaper.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
path Image file path, or NULL to clear</pre>
<p>Returns: true on success.</p>
<h3>dvxSetWallpaperMode</h3>
<pre><code>void dvxSetWallpaperMode(AppContextT *ctx, WallpaperModeE mode);</code></pre>
<p>Change the wallpaper display mode and re-render. No effect if no wallpaper is loaded.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
mode WallpaperStretchE, WallpaperTileE, or WallpaperCenterE</pre>
<h2>Mouse Configuration</h2>
<h3>dvxSetMouseConfig</h3>
<pre><code>void dvxSetMouseConfig(AppContextT *ctx, int32_t wheelDir, int32_t dblClickMs, int32_t accelThreshold, int32_t mickeyRatio, int32_t wheelStep);</code></pre>
<p>Configure mouse behavior. Updates the in-memory AppContextT fields and programs any INT 33h settings that need driver-side adjustment.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
wheelDir 1 = normal, -1 = reversed
dblClickMs Double-click speed in milliseconds (e.g. 500)
accelThreshold Double-speed threshold in mickeys/sec (0 = don't change)
mickeyRatio Mickeys per 8 pixels (0 = don't change, 8 = default speed)
wheelStep Lines to scroll per wheel notch (1-10, default 3)</pre>
<h2>Accelerators</h2>
<h3>dvxCreateAccelTable</h3>
<pre><code>AccelTableT *dvxCreateAccelTable(void);</code></pre>
<p>Allocate a new accelerator table. Attach to a window via win-&gt;accelTable.</p>
<p>Returns: Pointer to new AccelTableT.</p>
<h3>dvxFreeAccelTable</h3>
<pre><code>void dvxFreeAccelTable(AccelTableT *table);</code></pre>
<p>Free an accelerator table and its entries.</p>
<pre> Parameter Description
--------- -----------
table Table to free</pre>
<h3>dvxAddAccel</h3>
<pre><code>void dvxAddAccel(AccelTableT *table, int32_t key, int32_t modifiers, int32_t cmdId);</code></pre>
<p>Register a keyboard shortcut. On match, fires the window's onMenu callback with cmdId.</p>
<pre> Parameter Description
--------- -----------
table Accelerator table
key ASCII character or KEY_Fxx constant
modifiers Bitmask of ACCEL_CTRL / ACCEL_SHIFT / ACCEL_ALT
cmdId Command ID passed to onMenu</pre>
<h2>Window Arrangement</h2>
<h3>dvxCascadeWindows</h3>
<pre><code>void dvxCascadeWindows(AppContextT *ctx);</code></pre>
<p>Cascade all visible, non-minimized windows. Each is offset diagonally by the title bar height.</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h3>dvxTileWindows</h3>
<pre><code>void dvxTileWindows(AppContextT *ctx);</code></pre>
<p>Arrange visible windows in an NxM grid filling the screen.</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h3>dvxTileWindowsH</h3>
<pre><code>void dvxTileWindowsH(AppContextT *ctx);</code></pre>
<p>Tile windows horizontally (side by side, equal width, full height).</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h3>dvxTileWindowsV</h3>
<pre><code>void dvxTileWindowsV(AppContextT *ctx);</code></pre>
<p>Tile windows vertically (stacked, full width, equal height).</p>
<pre> Parameter Description
--------- -----------
ctx Application context</pre>
<h2>Image I/O</h2>
<h3>dvxLoadImage</h3>
<pre><code>uint8_t *dvxLoadImage(const AppContextT *ctx, const char *path, int32_t *outW, int32_t *outH, int32_t *outPitch);</code></pre>
<p>Load an image file (BMP, PNG, JPEG, GIF) and convert to the display's native pixel format. Caller must free with dvxFreeImage().</p>
<pre> Parameter Description
--------- -----------
ctx Application context
path Image file path
outW, outH Output: image dimensions
outPitch Output: row pitch in bytes</pre>
<p>Returns: Pixel buffer, or NULL on failure.</p>
<h3>dvxLoadImageFromMemory</h3>
<pre><code>uint8_t *dvxLoadImageFromMemory(const AppContextT *ctx, const uint8_t *data, int32_t dataLen, int32_t *outW, int32_t *outH, int32_t *outPitch);</code></pre>
<p>Load an image from a memory buffer (typically resource data). Same output format as dvxLoadImage(). Caller must free with dvxFreeImage().</p>
<pre> Parameter Description
--------- -----------
ctx Application context
data Image data buffer
dataLen Buffer size in bytes
outW, outH Output: image dimensions
outPitch Output: row pitch in bytes</pre>
<p>Returns: Pixel buffer, or NULL on failure.</p>
<h3>dvxLoadImageAlpha</h3>
<pre><code>uint8_t *dvxLoadImageAlpha(const AppContextT *ctx, const uint8_t *data, int32_t dataLen, int32_t *outW, int32_t *outH, int32_t *outPitch, bool *outHasAlpha, uint32_t *outKeyColor);</code></pre>
<p>Load an image from memory with alpha transparency. Pixels with alpha &lt; 128 are replaced with a packed magenta key color. If any transparent pixels are found, *outHasAlpha is set to true and *outKeyColor receives the packed key color for use with rectCopyTransparent. Caller must free with dvxFreeImage.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
data Image data buffer
dataLen Buffer size in bytes
outW, outH Output: image dimensions
outPitch Output: row pitch
outHasAlpha Output: true if any transparent pixels found
outKeyColor Output: packed key color (valid when outHasAlpha is true)</pre>
<p>Returns: Pixel buffer, or NULL on failure.</p>
<h3>dvxFreeImage</h3>
<pre><code>void dvxFreeImage(uint8_t *data);</code></pre>
<p>Free a pixel buffer returned by dvxLoadImage() or dvxLoadImageFromMemory().</p>
<pre> Parameter Description
--------- -----------
data Buffer to free</pre>
<h3>dvxImageInfo</h3>
<pre><code>bool dvxImageInfo(const char *path, int32_t *outW, int32_t *outH);</code></pre>
<p>Query image dimensions without decoding the full file.</p>
<pre> Parameter Description
--------- -----------
path Image file path
outW, outH Output: image dimensions</pre>
<p>Returns: true on success.</p>
<h3>dvxSaveImage</h3>
<pre><code>int32_t dvxSaveImage(const AppContextT *ctx, const uint8_t *data, int32_t w, int32_t h, int32_t pitch, const char *path);</code></pre>
<p>Save native-format pixel data to a PNG file.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
data Pixel data in display native format
w, h Image dimensions
pitch Row pitch in bytes
path Output file path</pre>
<p>Returns: 0 on success, -1 on failure.</p>
<h2>Screenshots</h2>
<h3>dvxScreenshot</h3>
<pre><code>int32_t dvxScreenshot(AppContextT *ctx, const char *path);</code></pre>
<p>Save the entire screen (backbuffer contents) to a PNG file. Converts from native pixel format to RGB.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
path Output PNG file path</pre>
<p>Returns: 0 on success, -1 on failure.</p>
<h3>dvxWindowScreenshot</h3>
<pre><code>int32_t dvxWindowScreenshot(AppContextT *ctx, WindowT *win, const char *path);</code></pre>
<p>Save a window's content to a PNG file.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window
path Output PNG file path</pre>
<p>Returns: 0 on success, -1 on failure.</p>
<h2>Clipboard</h2>
<h3>dvxClipboardCopy</h3>
<pre><code>void dvxClipboardCopy(const char *text, int32_t len);</code></pre>
<p>Copy text to the process-wide clipboard buffer. Simple static buffer (not inter-process).</p>
<pre> Parameter Description
--------- -----------
text Text to copy
len Length in bytes</pre>
<h3>dvxClipboardGet</h3>
<pre><code>const char *dvxClipboardGet(int32_t *outLen);</code></pre>
<p>Retrieve the current clipboard contents. Returns a pointer to the internal buffer (valid until the next dvxClipboardCopy), or NULL if empty.</p>
<pre> Parameter Description
--------- -----------
outLen Output: length of clipboard text</pre>
<p>Returns: Clipboard text, or NULL.</p>
<h2>Resource Loading</h2>
<h3>dvxResLoadIcon</h3>
<pre><code>uint8_t *dvxResLoadIcon(AppContextT *ctx, const char *dxePath, const char *resName, int32_t *outW, int32_t *outH, int32_t *outPitch);</code></pre>
<p>Load an icon/image resource from a DXE file and decode to native pixel format. Caller must free with dvxFreeImage().</p>
<pre> Parameter Description
--------- -----------
ctx Application context
dxePath Path to DXE file
resName Resource name within the DXE
outW, outH Output: image dimensions
outPitch Output: row pitch</pre>
<p>Returns: Pixel buffer, or NULL if not found.</p>
<h3>dvxResLoadText</h3>
<pre><code>bool dvxResLoadText(const char *dxePath, const char *resName, char *buf, int32_t bufSize);</code></pre>
<p>Load a text resource from a DXE file into a caller-provided buffer. Null-terminated and truncated to fit bufSize.</p>
<pre> Parameter Description
--------- -----------
dxePath Path to DXE file
resName Resource name
buf Output buffer
bufSize Buffer capacity</pre>
<p>Returns: true on success.</p>
<h3>dvxResLoadData</h3>
<pre><code>void *dvxResLoadData(const char *dxePath, const char *resName, uint32_t *outSize);</code></pre>
<p>Load a raw binary resource from a DXE file. Returns a malloc'd buffer that the caller must free.</p>
<pre> Parameter Description
--------- -----------
dxePath Path to DXE file
resName Resource name
outSize Output: data size in bytes</pre>
<p>Returns: Data buffer, or NULL if not found.</p>
<h2>Utilities</h2>
<h3>dvxTextHash</h3>
<pre><code>uint32_t dvxTextHash(const char *text);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
text Null-terminated string to hash</pre>
<p>Returns: 32-bit hash value.</p>
</div>
<div class="topic" id="api.widget">
<h1>dvxWgt.h -- Widget System</h1>
<p>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>
<h2>WidgetT Structure</h2>
<p>Core widget structure. Generic across all widget types; type-specific data lives in the void *data pointer managed by each widget's DXE.</p>
<pre> Field Description
----- -----------
int32_t type Widget type ID (assigned by wgtRegisterClass)
const WidgetClassT *wclass Vtable for this widget type
char name[MAX_WIDGET_NAME] Widget name for lookup via wgtFind
parent, firstChild, lastChild, nextSibling Tree linkage pointers
WindowT *window Owning window
int32_t x, y, w, h Computed geometry (relative to content area)
int32_t calcMinW, calcMinH Computed minimum size (from layout pass)
int32_t minW, minH, maxW, maxH, prefW, prefH Size hints (tagged sizes)
int32_t weight Extra-space distribution weight (0=fixed, 100=normal)
WidgetAlignE align Main-axis alignment for children
int32_t spacing, padding Tagged sizes for child spacing and padding
uint32_t fgColor, bgColor Custom colors (0 = use scheme defaults)
bool visible, enabled, readOnly State flags
bool swallowTab Tab key goes to widget, not focus navigation
bool paintDirty Needs repaint (set by wgtInvalidatePaint)
bool childDirty A descendant needs repaint (for WCLASS_PAINTS_CHILDREN)
bool pressed WCLASS_PRESS_RELEASE: set while button is pressed
char accelKey Accelerator character (0 = none)
int32_t contentOffX, contentOffY Content offset for mouse event coordinates
void *userData, *data Application data and widget-private data
const char *tooltip Tooltip text (NULL = none)
MenuT *contextMenu Right-click menu (NULL = none)</pre>
<p>Universal Callbacks:</p>
<pre> Callback Description
-------- -----------
onClick(WidgetT *w) Widget clicked
onDblClick(WidgetT *w) Widget double-clicked
onChange(WidgetT *w) Value changed
onFocus(WidgetT *w) Widget gained focus
onBlur(WidgetT *w) Widget lost focus
onKeyPress(WidgetT *w, int32_t keyAscii) ASCII key press
onKeyDown(WidgetT *w, int32_t keyCode, int32_t shift) Key down
onKeyUp(WidgetT *w, int32_t keyCode, int32_t shift) Key up
onMouseDown(WidgetT *w, int32_t button, int32_t x, int32_t y) Mouse button pressed
onMouseUp(WidgetT *w, int32_t button, int32_t x, int32_t y) Mouse button released
onMouseMove(WidgetT *w, int32_t button, int32_t x, int32_t y) Mouse moved
onScroll(WidgetT *w, int32_t delta) Mouse wheel
onValidate(WidgetT *w) Return false to cancel a write</pre>
<h2>Size Specification Macros</h2>
<pre> Macro Description
----- -----------
wgtPixels(v) Size in pixels
wgtChars(v) Size in character widths (multiplied by charWidth at layout)
wgtPercent(v) Size as percentage of parent dimension</pre>
<h2>Widget Class Flags</h2>
<pre> Flag Description
---- -----------
WCLASS_FOCUSABLE Can receive keyboard focus (Tab navigation)
WCLASS_HORIZ_CONTAINER Lays out children horizontally (vs. vertical)
WCLASS_PAINTS_CHILDREN Widget handles child rendering itself
WCLASS_NO_HIT_RECURSE Hit testing stops here, no child recursion
WCLASS_FOCUS_FORWARD Accel hit forwards focus to next focusable sibling
WCLASS_HAS_POPUP Has dropdown popup overlay
WCLASS_SCROLLABLE Accepts mouse wheel events
WCLASS_SCROLL_CONTAINER Scroll container (ScrollPane)
WCLASS_NEEDS_POLL Needs periodic polling
WCLASS_SWALLOWS_TAB Tab key goes to widget, not focus navigation
WCLASS_RELAYOUT_ON_SCROLL Full relayout on scrollbar drag
WCLASS_PRESS_RELEASE Click = press + release (Button, ImageButton)
WCLASS_ACCEL_WHEN_HIDDEN Accelerator matching works even when invisible</pre>
<h2>Window Integration</h2>
<h3>wgtInitWindow</h3>
<pre><code>WidgetT *wgtInitWindow(AppContextT *ctx, WindowT *win);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
ctx Application context
win Window to initialize</pre>
<p>Returns: Root VBox widget (add children to this).</p>
<h2>Widget Operations</h2>
<h3>wgtGetContext</h3>
<pre><code>AppContextT *wgtGetContext(const WidgetT *w);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
w Any widget in the tree</pre>
<p>Returns: Pointer to the AppContextT.</p>
<h3>wgtInvalidate</h3>
<pre><code>void wgtInvalidate(WidgetT *w);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
w Widget to invalidate</pre>
<h3>wgtInvalidatePaint</h3>
<pre><code>void wgtInvalidatePaint(WidgetT *w);</code></pre>
<p>Mark a widget as needing repaint only, without re-layout. Use for visual-only changes (checkbox toggle, selection highlight, cursor blink).</p>
<pre> Parameter Description
--------- -----------
w Widget to repaint</pre>
<h3>wgtSetText</h3>
<pre><code>void wgtSetText(WidgetT *w, const char *text);</code></pre>
<p>Set widget text content (dispatches to the widget class's SET_TEXT handler).</p>
<pre> Parameter Description
--------- -----------
w Widget
text New text</pre>
<h3>wgtGetText</h3>
<pre><code>const char *wgtGetText(const WidgetT *w);</code></pre>
<p>Get the widget's current text content.</p>
<pre> Parameter Description
--------- -----------
w Widget</pre>
<p>Returns: Text string (empty string if no handler).</p>
<h3>wgtSetEnabled</h3>
<pre><code>void wgtSetEnabled(WidgetT *w, bool enabled);</code></pre>
<p>Enable or disable a widget. Disabled widgets are grayed out and do not receive input.</p>
<pre> Parameter Description
--------- -----------
w Widget
enabled true = enabled, false = disabled</pre>
<h3>wgtSetReadOnly</h3>
<pre><code>void wgtSetReadOnly(WidgetT *w, bool readOnly);</code></pre>
<p>Set read-only mode. Allows scrolling and selection but blocks editing.</p>
<pre> Parameter Description
--------- -----------
w Widget
readOnly true = read-only</pre>
<h3>wgtSetFocused</h3>
<pre><code>void wgtSetFocused(WidgetT *w);</code></pre>
<p>Set keyboard focus to a widget.</p>
<pre> Parameter Description
--------- -----------
w Widget to focus</pre>
<h3>wgtGetFocused</h3>
<pre><code>WidgetT *wgtGetFocused(void);</code></pre>
<p>Get the currently focused widget.</p>
<p>Returns: Focused widget, or NULL.</p>
<h3>wgtSetVisible</h3>
<pre><code>void wgtSetVisible(WidgetT *w, bool visible);</code></pre>
<p>Show or hide a widget.</p>
<pre> Parameter Description
--------- -----------
w Widget
visible true = visible, false = hidden</pre>
<h3>wgtSetName</h3>
<pre><code>void wgtSetName(WidgetT *w, const char *name);</code></pre>
<p>Set a widget's name for lookup via wgtFind().</p>
<pre> Parameter Description
--------- -----------
w Widget
name Name string (max MAX_WIDGET_NAME chars)</pre>
<h3>wgtFind</h3>
<pre><code>WidgetT *wgtFind(WidgetT *root, const char *name);</code></pre>
<p>Find a widget by name. Searches the subtree rooted at root.</p>
<pre> Parameter Description
--------- -----------
root Root of subtree to search
name Widget name to find</pre>
<p>Returns: Matching widget, or NULL.</p>
<h3>wgtDestroy</h3>
<pre><code>void wgtDestroy(WidgetT *w);</code></pre>
<p>Destroy a widget and all its children. Removes from parent's child list.</p>
<pre> Parameter Description
--------- -----------
w Widget to destroy</pre>
<h3>wgtSetTooltip</h3>
<pre><code>void wgtSetTooltip(WidgetT *w, const char *text);</code></pre>
<p>Set tooltip text for a widget. Pass NULL to remove. Caller owns the string and it must outlive the widget.</p>
<pre> Parameter Description
--------- -----------
w Widget
text Tooltip text, or NULL</pre>
<h3>widgetOnResize</h3>
<pre><code>void widgetOnResize(WindowT *win, int32_t newW, int32_t newH);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
win Window being resized
newW, newH New content dimensions</pre>
<h2>Layout</h2>
<h3>wgtResolveSize</h3>
<pre><code>int32_t wgtResolveSize(int32_t taggedSize, int32_t parentSize, int32_t charWidth);</code></pre>
<p>Decode a tagged size value (WGT_SIZE_PIXELS/CHARS/PERCENT) into a concrete pixel count. Returns 0 for a raw 0 input (meaning &quot;auto&quot;).</p>
<pre> Parameter Description
--------- -----------
taggedSize Tagged size value
parentSize Parent dimension (for PERCENT mode)
charWidth Font character width (for CHARS mode)</pre>
<p>Returns: Size in pixels.</p>
<h3>wgtLayout</h3>
<pre><code>void wgtLayout(WidgetT *root, int32_t availW, int32_t availH, const BitmapFontT *font);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
root Root widget
availW/H Available space
font Bitmap font (for character-based sizing)</pre>
<h3>wgtPaint</h3>
<pre><code>void wgtPaint(WidgetT *root, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors, bool fullRepaint);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
root Root widget
d Display context
ops Blit operations vtable
font Bitmap font
colors Color scheme
fullRepaint true = repaint every widget; false = only paintDirty widgets</pre>
<h2>Debug</h2>
<h3>wgtSetDebugLayout</h3>
<pre><code>void wgtSetDebugLayout(AppContextT *ctx, bool enabled);</code></pre>
<p>Draw colored borders around layout containers for debugging.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
enabled true = draw debug borders</pre>
<h2>Dynamic Widget Registration</h2>
<h3>wgtRegisterClass</h3>
<pre><code>int32_t wgtRegisterClass(const WidgetClassT *wclass);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
wclass Widget class vtable to register</pre>
<p>Returns: Assigned type ID.</p>
<h3>wgtRegisterApi</h3>
<pre><code>void wgtRegisterApi(const char *name, const void *api);</code></pre>
<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>
<pre> Parameter Description
--------- -----------
name Widget type name (e.g. &quot;button&quot;, &quot;listbox&quot;)
api Pointer to the widget's API struct</pre>
<blockquote><strong>Warning:</strong> The create function must be the first field of the API struct. BASIC's form runtime instantiates widgets by dereferencing the api pointer as a pointer-to-function-pointer (see createWidgetByIface), so whichever field is first is what gets invoked. If the struct has multiple constructor variants, the one matching createSig must come first; put helper constructors, index accessors, and other entry points after it.</blockquote>
<h3>wgtGetApi</h3>
<pre><code>const void *wgtGetApi(const char *name);</code></pre>
<p>Retrieve a registered widget API struct by name.</p>
<pre> Parameter Description
--------- -----------
name Widget type name</pre>
<p>Returns: Pointer to the API struct, or NULL if not found.</p>
<h2>Widget Interface Descriptors</h2>
<h3>wgtRegisterIface</h3>
<pre><code>void wgtRegisterIface(const char *name, const WgtIfaceT *iface);</code></pre>
<p>Register an interface descriptor for a widget type. Used by the BASIC form runtime and IDE for generic property/method dispatch.</p>
<pre> Parameter Description
--------- -----------
name Widget type name
iface Interface descriptor</pre>
<h3>wgtGetIface</h3>
<pre><code>const WgtIfaceT *wgtGetIface(const char *name);</code></pre>
<p>Retrieve an interface descriptor by widget type name.</p>
<pre> Parameter Description
--------- -----------
name Widget type name</pre>
<p>Returns: Interface descriptor, or NULL.</p>
<h3>wgtFindByBasName</h3>
<pre><code>const char *wgtFindByBasName(const char *basName);</code></pre>
<p>Find a widget type name by its VB-style name (e.g. &quot;CommandButton&quot; -&gt; &quot;button&quot;). Case-insensitive search.</p>
<pre> Parameter Description
--------- -----------
basName VB-style widget name</pre>
<p>Returns: Internal type name, or NULL.</p>
<h3>wgtIfaceCount</h3>
<pre><code>int32_t wgtIfaceCount(void);</code></pre>
<p>Return the number of registered widget interfaces.</p>
<p>Returns: Count of registered interfaces.</p>
<h3>wgtIfaceAt</h3>
<pre><code>const WgtIfaceT *wgtIfaceAt(int32_t idx, const char **outName);</code></pre>
<p>Get a registered widget interface by index.</p>
<pre> Parameter Description
--------- -----------
idx Index (0-based)
outName Output: type name</pre>
<p>Returns: Interface descriptor.</p>
<h3>wgtIfaceGetPath</h3>
<pre><code>const char *wgtIfaceGetPath(const char *name);</code></pre>
<p>Get the .wgt DXE file path for a registered widget.</p>
<pre> Parameter Description
--------- -----------
name Widget type name</pre>
<p>Returns: File path string.</p>
<h3>wgtIfaceSetPath</h3>
<pre><code>void wgtIfaceSetPath(const char *name, const char *path);</code></pre>
<p>Set the .wgt DXE file path for a registered widget (called by the loader).</p>
<pre> Parameter Description
--------- -----------
name Widget type name
path DXE file path</pre>
<h3>wgtIfaceGetPathIndex</h3>
<pre><code>int32_t wgtIfaceGetPathIndex(const char *name);</code></pre>
<p>Get the 1-based index of this widget within its .wgt file. Used to construct suffixed resource names (e.g. &quot;name-2&quot;, &quot;icon16-2&quot;).</p>
<pre> Parameter Description
--------- -----------
name Widget type name</pre>
<p>Returns: 1-based index within the DXE file.</p>
<h2>Typed Dispatch Helpers</h2>
<p>The following inline functions provide type-safe dispatch through the WidgetClassT handler table. Each checks for a non-NULL handler before calling.</p>
<pre> Function Method ID Description
-------- --------- -----------
wclsHas(w, methodId) -- Check if handler exists
wclsPaint(w, d, ops, font, colors) WGT_METHOD_PAINT Paint the widget
wclsPaintOverlay(w, d, ops, font, colors) WGT_METHOD_PAINT_OVERLAY Paint overlay (popups)
wclsCalcMinSize(w, font) WGT_METHOD_CALC_MIN_SIZE Compute minimum size
wclsLayout(w, font) WGT_METHOD_LAYOUT Layout children
wclsGetLayoutMetrics(w, font, ...) WGT_METHOD_GET_LAYOUT_METRICS Get pad, gap, extraTop, borderW
wclsOnMouse(w, root, vx, vy) WGT_METHOD_ON_MOUSE Handle mouse event
wclsOnKey(w, key, mod) WGT_METHOD_ON_KEY Handle key event
wclsOnAccelActivate(w, root) WGT_METHOD_ON_ACCEL_ACTIVATE Handle accelerator
wclsDestroy(w) WGT_METHOD_DESTROY Destroy widget data
wclsOnChildChanged(parent, child) WGT_METHOD_ON_CHILD_CHANGED Notify parent of change
wclsGetText(w) WGT_METHOD_GET_TEXT Get widget text
wclsSetText(w, text) WGT_METHOD_SET_TEXT Set widget text
wclsClearSelection(w) WGT_METHOD_CLEAR_SELECTION Clear text selection
wclsClosePopup(w) WGT_METHOD_CLOSE_POPUP Close dropdown popup
wclsGetPopupRect(w, font, ...) WGT_METHOD_GET_POPUP_RECT Get popup screen rect
wclsOnDragUpdate(w, root, x, y) WGT_METHOD_ON_DRAG_UPDATE Update during drag
wclsOnDragEnd(w, root, x, y) WGT_METHOD_ON_DRAG_END End drag operation
wclsGetCursorShape(w, vx, vy) WGT_METHOD_GET_CURSOR_SHAPE Get cursor for position
wclsPoll(w, win) WGT_METHOD_POLL Periodic polling
wclsQuickRepaint(w, outY, outH) WGT_METHOD_QUICK_REPAINT Fast partial repaint
wclsScrollChildIntoView(parent, child) WGT_METHOD_SCROLL_CHILD_INTO_VIEW Scroll child visible</pre>
<h2>Method IDs</h2>
<p>Fixed constants used to index into WidgetClassT.handlers[]. Method IDs are stable ABI -- new methods are appended at the next sequential ID, never reordered or reused.</p>
<pre> ID Symbol Signature
-- ------ ---------
0 WGT_METHOD_PAINT void (w, d, ops, font, colors)
1 WGT_METHOD_PAINT_OVERLAY void (w, d, ops, font, colors)
2 WGT_METHOD_CALC_MIN_SIZE void (w, font)
3 WGT_METHOD_LAYOUT void (w, font)
4 WGT_METHOD_GET_LAYOUT_METRICS void (w, font, pad, gap, extraTop, borderW)
5 WGT_METHOD_ON_MOUSE void (w, root, vx, vy)
6 WGT_METHOD_ON_KEY void (w, key, mod)
7 WGT_METHOD_ON_ACCEL_ACTIVATE void (w, root)
8 WGT_METHOD_DESTROY void (w)
9 WGT_METHOD_ON_CHILD_CHANGED void (parent, child)
10 WGT_METHOD_GET_TEXT const char *(w)
11 WGT_METHOD_SET_TEXT void (w, text)
12 WGT_METHOD_CLEAR_SELECTION bool (w)
13 WGT_METHOD_CLOSE_POPUP void (w)
14 WGT_METHOD_GET_POPUP_RECT void (w, font, contentH, popX, popY, popW, popH)
15 WGT_METHOD_ON_DRAG_UPDATE void (w, root, x, y)
16 WGT_METHOD_ON_DRAG_END void (w, root, x, y)
17 WGT_METHOD_GET_CURSOR_SHAPE int32_t (w, vx, vy)
18 WGT_METHOD_POLL void (w, win)
19 WGT_METHOD_QUICK_REPAINT int32_t (w, outY, outH)
20 WGT_METHOD_SCROLL_CHILD_INTO_VIEW void (parent, child)
-- WGT_METHOD_COUNT = 21, WGT_METHOD_MAX = 32</pre>
<p>WGT_CLASS_VERSION is bumped on breaking ABI changes. The framework rejects WidgetClassT structs whose version does not match.</p>
<h2>Widget Class Dispatch Table</h2>
<h3>WidgetClassT</h3>
<pre><code>typedef struct WidgetClassT {
uint32_t version;
uint32_t flags;
void *handlers[WGT_METHOD_MAX];
} WidgetClassT;</code></pre>
<pre> Field Description
----- -----------
version Must equal WGT_CLASS_VERSION at registration
flags Bitmask of WCLASS_xxx flags
handlers Array of 32 function pointers indexed by WGT_METHOD_xxx</pre>
<h2>Size Encoding Constants</h2>
<pre> Define Value Description
------ ----- -----------
WGT_SIZE_TYPE_MASK 0xC0000000 Top 2 bits: unit type selector
WGT_SIZE_VAL_MASK 0x3FFFFFFF Bottom 30 bits: numeric value
WGT_SIZE_PIXELS 0x00000000 Unit tag: pixels
WGT_SIZE_CHARS 0x40000000 Unit tag: character widths
WGT_SIZE_PERCENT 0x80000000 Unit tag: percentage of parent
WGT_WEIGHT_FILL 100 Default &quot;flexible&quot; weight value</pre>
<h2>Widget Interface Descriptors</h2>
<h3>WgtPropDescT</h3>
<p>Describes a BASIC-exposed property on a widget type. Used by the form runtime and IDE for generic get/set dispatch.</p>
<pre> Field Description
----- -----------
name BASIC property name (e.g. &quot;Caption&quot;, &quot;Value&quot;)
type Data type: WGT_IFACE_STRING, WGT_IFACE_INT, WGT_IFACE_BOOL, WGT_IFACE_FLOAT, or WGT_IFACE_ENUM
getFn Getter function pointer (NULL if write-only)
setFn Setter function pointer (NULL if read-only)
enumNames For WGT_IFACE_ENUM: NULL-terminated array of value names</pre>
<h3>WgtMethodDescT</h3>
<p>Describes an invokable method on a widget type.</p>
<pre> Field Description
----- -----------
name BASIC method name (e.g. &quot;Clear&quot;, &quot;SetFocus&quot;)
sig Calling convention ID (WGT_SIG_xxx)
fn Function pointer</pre>
<h3>WgtEventDescT</h3>
<p>Describes an event beyond the standard common set (Click, DblClick, Change, GotFocus, LostFocus).</p>
<pre> Field Description
----- -----------
name Event name (e.g. &quot;Change&quot;, &quot;Timer&quot;)</pre>
<h3>WgtIfaceT</h3>
<p>Top-level interface descriptor registered by each widget DXE.</p>
<pre> Field Description
----- -----------
basName VB-style name (e.g. &quot;CommandButton&quot;), or NULL
props Array of WgtPropDescT
propCount Length of props array
methods Array of WgtMethodDescT
methodCount Length of methods array
events Array of WgtEventDescT (extras beyond common set)
eventCount Length of events array
createSig How to call the widget's create() function (WgtCreateSigE)
createArgs Default numeric args for design-time instantiation
isContainer true = widget can hold child widgets
defaultEvent Default event name for form designer
namePrefix Auto-name prefix (NULL = derive from basName)</pre>
<h2>Property Data Type Constants</h2>
<pre> Define Value Description
------ ----- -----------
WGT_IFACE_STRING 0 const char *
WGT_IFACE_INT 1 int32_t
WGT_IFACE_BOOL 2 bool
WGT_IFACE_FLOAT 3 float
WGT_IFACE_ENUM 4 int32_t with named values</pre>
<h2>Create Function Signature Constants</h2>
<pre> Define Value Form
------ ----- ----
WGT_CREATE_PARENT 0 fn(parent)
WGT_CREATE_PARENT_TEXT 1 fn(parent, const char *text)
WGT_CREATE_PARENT_INT 2 fn(parent, int32_t)
WGT_CREATE_PARENT_INT_INT 3 fn(parent, int32_t, int32_t)
WGT_CREATE_PARENT_INT_INT_INT 4 fn(parent, int32_t, int32_t, int32_t)
WGT_CREATE_PARENT_INT_BOOL 5 fn(parent, int32_t, bool)
WGT_CREATE_PARENT_BOOL 6 fn(parent, bool)
WGT_CREATE_PARENT_DATA 7 fn(parent, data, w, h, pitch) -- not auto-creatable</pre>
<p>WGT_MAX_CREATE_ARGS is 3.</p>
</div>
<div class="topic" id="api.dialog">
<h1>dvxDlg.h -- Modal Dialogs</h1>
<p>Pre-built modal dialog boxes that block the caller and run their own event loop via dvxUpdate() until the user dismisses them. Modal dialogs set ctx-&gt;modalWindow to prevent input from reaching other windows for the dialog's lifetime.</p>
<h2>Message Box Flags</h2>
<p>Button configurations (low nibble):</p>
<pre> Define Value Description
------ ----- -----------
MB_OK 0x0000 OK button only (default)
MB_OKCANCEL 0x0001 OK and Cancel
MB_YESNO 0x0002 Yes and No
MB_YESNOCANCEL 0x0003 Yes, No, and Cancel
MB_RETRYCANCEL 0x0004 Retry and Cancel</pre>
<p>Icon types (high nibble, OR with button flags):</p>
<pre> Define Value Description
------ ----- -----------
MB_ICONINFO 0x0010 Information icon
MB_ICONWARNING 0x0020 Warning icon
MB_ICONERROR 0x0030 Error icon
MB_ICONQUESTION 0x0040 Question mark icon</pre>
<p>Return values:</p>
<pre> Define Value Button pressed
------ ----- --------------
ID_OK 1 OK
ID_CANCEL 2 Cancel or dialog closed
ID_YES 3 Yes
ID_NO 4 No
ID_RETRY 5 Retry</pre>
<h2>dvxMessageBox</h2>
<pre><code>int32_t dvxMessageBox(AppContextT *ctx, const char *title, const char *message, int32_t flags);</code></pre>
<p>Display a modal message box. Blocks the caller by running dvxUpdate() in a loop until a button is pressed or the dialog is closed. The window is automatically destroyed on return.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Window title (NULL falls back to a generic default)
message Body text
flags MB_xxx button + icon flags, OR'd together</pre>
<p>Returns: ID_xxx of the button that was pressed.</p>
<pre><code>// Example: yes/no confirmation
int32_t r = dvxMessageBox(ctx, &quot;Save&quot;, &quot;Save changes before closing?&quot;, MB_YESNOCANCEL | MB_ICONQUESTION);
if (r == ID_YES) { saveFile(); }</code></pre>
<h2>dvxErrorBox</h2>
<pre><code>int32_t dvxErrorBox(AppContextT *ctx, const char *title, const char *message);</code></pre>
<p>Convenience wrapper for MB_OK | MB_ICONERROR. Title defaults to &quot;Error&quot; when NULL.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Dialog title, or NULL for &quot;Error&quot;
message Error message</pre>
<p>Returns: ID_OK.</p>
<h2>dvxInfoBox</h2>
<pre><code>int32_t dvxInfoBox(AppContextT *ctx, const char *title, const char *message);</code></pre>
<p>Convenience wrapper for MB_OK | MB_ICONINFO.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Dialog title
message Informational message</pre>
<p>Returns: ID_OK.</p>
<h2>File Dialog</h2>
<h3>FileFilterT</h3>
<p>Describes a filter entry in the file dialog's format dropdown. The glob pattern is extracted from inside the parentheses.</p>
<pre> Field Description
----- -----------
label e.g. &quot;Text Files (*.txt)&quot; or &quot;Images (*.bmp;*.png;*.jpg;*.gif)&quot;</pre>
<h3>File Dialog Flags</h3>
<pre> Define Value Description
------ ----- -----------
FD_OPEN 0x0000 File open dialog (default)
FD_SAVE 0x0001 File save dialog (with overwrite prompt)</pre>
<h3>dvxFileDialog</h3>
<pre><code>bool dvxFileDialog(AppContextT *ctx, const char *title, int32_t flags, const char *initialDir, const FileFilterT *filters, int32_t filterCount, char *outPath, int32_t outPathSize);</code></pre>
<p>Display a modal file open/save dialog. Shows a directory listing with parent/drive-letter navigation, a filename input, and an optional filter dropdown.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Window title
flags FD_OPEN or FD_SAVE
initialDir Starting directory (NULL = current working directory)
filters Array of FileFilterT, or NULL
filterCount Number of filter entries
outPath Output buffer for selected path
outPathSize Capacity of outPath buffer</pre>
<p>Returns: true if the user selected a file, false if cancelled or closed.</p>
<h2>Input Boxes</h2>
<h3>dvxInputBox</h3>
<pre><code>bool dvxInputBox(AppContextT *ctx, const char *title, const char *prompt, const char *defaultText, char *outBuf, int32_t outBufSize);</code></pre>
<p>Display a modal input box with a prompt label, text field, and OK/Cancel buttons.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Window title
prompt Prompt label above the input field
defaultText Initial text (NULL = empty)
outBuf Output buffer
outBufSize Capacity of outBuf</pre>
<p>Returns: true if OK was pressed, false if cancelled.</p>
<h3>dvxIntInputBox</h3>
<pre><code>bool dvxIntInputBox(AppContextT *ctx, const char *title, const char *prompt, int32_t defaultVal, int32_t minVal, int32_t maxVal, int32_t step, int32_t *outVal);</code></pre>
<p>Display a modal integer input box with a spinner (up/down arrows) for clamped numeric input.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Window title
prompt Prompt label
defaultVal Initial value
minVal Minimum allowed value
maxVal Maximum allowed value
step Increment per arrow click
outVal Output: entered value</pre>
<p>Returns: true if OK pressed, false if cancelled.</p>
<h2>Choice Dialog</h2>
<h3>dvxChoiceDialog</h3>
<pre><code>bool dvxChoiceDialog(AppContextT *ctx, const char *title, const char *prompt, const char **items, int32_t itemCount, int32_t defaultIdx, int32_t *outIdx);</code></pre>
<p>Display a modal dialog with a listbox of choices. The user picks one item and clicks OK, or cancels.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Window title
prompt Prompt label above the list
items Array of choice strings
itemCount Number of items
defaultIdx Initially highlighted item (-1 = none)
outIdx Output: selected index</pre>
<p>Returns: true if a choice was made, false if cancelled.</p>
<h2>Save Prompt</h2>
<p>Return codes for dvxPromptSave:</p>
<pre> Define Value Action
------ ----- ------
DVX_SAVE_YES 1 Save, then proceed
DVX_SAVE_NO 2 Discard, then proceed
DVX_SAVE_CANCEL 3 Abort the operation</pre>
<h3>dvxPromptSave</h3>
<pre><code>int32_t dvxPromptSave(AppContextT *ctx, const char *title);</code></pre>
<p>Display a canonical &quot;Save changes?&quot; dialog with Yes/No/Cancel buttons and an appropriate question icon.</p>
<pre> Parameter Description
--------- -----------
ctx Application context
title Document name for message context</pre>
<p>Returns: DVX_SAVE_YES, DVX_SAVE_NO, or DVX_SAVE_CANCEL.</p>
</div>
<div class="topic" id="api.resource">
<h1>dvxRes.h -- DXE-Embedded Resource System</h1>
<p>Resources are appended to DXE3 files (.app, .wgt, .lib) after the normal DXE content. The DXE loader never reads past its own header-specified sections, so the appended resource block is invisible to dlopen. This lets each DXE carry its own icons, localized text, help content, and binary data without separate resource files.</p>
<h2>File Layout</h2>
<pre><code>[DXE3 content] -- untouched, loaded by dlopen
[resource data entries] -- sequential, variable length
[resource directory] -- fixed-size entries (48 bytes each)
[footer] -- magic + directory offset + entry count (16 bytes)</code></pre>
<p>Reading starts from the end: seek to EOF - sizeof(footer), verify the magic, then seek to the directory.</p>
<h2>Constants</h2>
<pre> Define Value Description
------ ----- -----------
DVX_RES_ICON 1 Image data (BMP, PNG, etc.)
DVX_RES_TEXT 2 Null-terminated string
DVX_RES_BINARY 3 Arbitrary binary data (app-specific)
DVX_RES_MAGIC 0x52585644 Footer signature (&quot;DVXR&quot; little-endian)
DVX_RES_NAME_MAX 32 Max resource name length including null</pre>
<h2>Structures</h2>
<h3>DvxResDirEntryT</h3>
<p>Directory entry describing one resource (48 bytes on disk).</p>
<pre> Field Description
----- -----------
name Resource name (up to 32 chars, null-terminated)
type DVX_RES_ICON, DVX_RES_TEXT, or DVX_RES_BINARY
offset Absolute file offset of the data
size Data size in bytes
reserved Padding (must be zero)</pre>
<h3>DvxResFooterT</h3>
<p>Footer at the very end of a DXE file with appended resources (16 bytes).</p>
<pre> Field Description
----- -----------
magic DVX_RES_MAGIC
dirOffset Absolute file offset of the resource directory
entryCount Number of directory entries
reserved Padding (must be zero)</pre>
<h3>DvxResHandleT</h3>
<p>Opaque runtime handle representing an open resource block.</p>
<pre> Field Description
----- -----------
path Source file path
entries Directory entries (sorted by name for bsearch)
entryCount Number of entries</pre>
<h2>Runtime API</h2>
<h3>dvxResOpen</h3>
<pre><code>DvxResHandleT *dvxResOpen(const char *path);</code></pre>
<p>Open a resource handle by reading the footer and directory. Returns NULL if the file has no resource block or cannot be read. Entries are sorted on open for O(log n) name lookup via bsearch.</p>
<pre> Parameter Description
--------- -----------
path Path to the DXE (or any file) with appended resources</pre>
<p>Returns: Handle pointer, or NULL.</p>
<h3>dvxResRead</h3>
<pre><code>void *dvxResRead(DvxResHandleT *h, const char *name, uint32_t *outSize);</code></pre>
<p>Find a resource by name and read its data into a freshly malloc'd buffer. Caller must free the returned buffer.</p>
<pre> Parameter Description
--------- -----------
h Resource handle
name Resource name
outSize Output: data size in bytes</pre>
<p>Returns: Data buffer, or NULL if not found or I/O failed.</p>
<h3>dvxResFind</h3>
<pre><code>const DvxResDirEntryT *dvxResFind(DvxResHandleT *h, const char *name);</code></pre>
<p>Look up a resource's directory entry by name. The returned pointer is valid until dvxResClose.</p>
<pre> Parameter Description
--------- -----------
h Resource handle
name Resource name</pre>
<p>Returns: Pointer to directory entry, or NULL if not found.</p>
<h3>dvxResClose</h3>
<pre><code>void dvxResClose(DvxResHandleT *h);</code></pre>
<p>Close a resource handle and free its memory.</p>
<pre> Parameter Description
--------- -----------
h Handle to close</pre>
<h3>dvxResAppend</h3>
<pre><code>int32_t dvxResAppend(const char *path, const char *name, uint32_t type, const void *data, uint32_t dataSize);</code></pre>
<p>Append a resource to an existing DXE file. Preserves existing resources and adds the new one. Thin wrapper over the resource writer in tools/dvxResWrite.h.</p>
<pre> Parameter Description
--------- -----------
path Target DXE path
name Resource name (up to DVX_RES_NAME_MAX - 1 chars)
type DVX_RES_ICON, DVX_RES_TEXT, or DVX_RES_BINARY
data Resource payload
dataSize Payload size in bytes</pre>
<p>Returns: 0 on success, -1 on failure.</p>
<h3>dvxResRemove</h3>
<pre><code>int32_t dvxResRemove(const char *path, const char *name);</code></pre>
<p>Remove a resource from a DXE file by name. If this was the last resource, the file is truncated back to the original DXE content.</p>
<pre> Parameter Description
--------- -----------
path Target DXE path
name Resource name to remove</pre>
<p>Returns: 0 on success, -1 if not found or I/O failed.</p>
<h2>See Also</h2>
<p><a href="#api.app">dvxResLoadIcon / dvxResLoadText / dvxResLoadData -- higher-level helpers on top of this API</a></p>
</div>
<div class="topic" id="api.prefs">
<h1>dvxPrefs.h -- INI Preferences System</h1>
<p>Handle-based API over classic INI files. Each prefsLoad/prefsCreate returns a PrefsHandleT that must be passed to all subsequent calls and freed with prefsClose when done. Multiple INI files can be open simultaneously.</p>
<h2>Constants</h2>
<pre> Define Value Description
------ ----- -----------
DVX_INI_PATH &quot;CONFIG&quot; DVX_PATH_SEP &quot;DVX.INI&quot; Canonical system INI path</pre>
<h2>Types</h2>
<h3>PrefsHandleT</h3>
<p>Opaque handle representing an in-memory INI file. Fields are not exposed.</p>
<h2>Lifecycle</h2>
<h3>prefsCreate</h3>
<pre><code>PrefsHandleT *prefsCreate(void);</code></pre>
<p>Create an empty preferences handle with no associated file. Use this when building an INI from scratch before calling prefsSaveAs.</p>
<p>Returns: New handle, or NULL on allocation failure.</p>
<h3>prefsLoad</h3>
<pre><code>PrefsHandleT *prefsLoad(const char *filename);</code></pre>
<p>Load an INI file into a new handle. If the file does not exist, returns a valid empty handle with the path stored so prefsSave can write a new file later.</p>
<pre> Parameter Description
--------- -----------
filename Path to INI file</pre>
<p>Returns: Handle, or NULL on allocation failure.</p>
<h3>prefsSave</h3>
<pre><code>bool prefsSave(PrefsHandleT *h);</code></pre>
<p>Save the in-memory state back to the file that was loaded (or captured by prefsLoad for a non-existent file).</p>
<pre> Parameter Description
--------- -----------
h Preferences handle</pre>
<p>Returns: true on success.</p>
<h3>prefsSaveAs</h3>
<pre><code>bool prefsSaveAs(PrefsHandleT *h, const char *filename);</code></pre>
<p>Save to a specific file, overriding the handle's stored path.</p>
<pre> Parameter Description
--------- -----------
h Preferences handle
filename Output file path</pre>
<p>Returns: true on success.</p>
<h3>prefsClose</h3>
<pre><code>void prefsClose(PrefsHandleT *h);</code></pre>
<p>Release all memory held by the handle. Does not save -- call prefsSave first if needed.</p>
<pre> Parameter Description
--------- -----------
h Handle to close</pre>
<h2>Getters</h2>
<h3>prefsGetString</h3>
<pre><code>const char *prefsGetString(PrefsHandleT *h, const char *section, const char *key, const char *defaultVal);</code></pre>
<p>Retrieve a string value from [section]/key. The returned pointer is valid until the key is modified or the handle is closed.</p>
<pre> Parameter Description
--------- -----------
h Preferences handle
section Section name (without brackets)
key Key name
defaultVal Returned if the key is not present</pre>
<p>Returns: Key value or defaultVal.</p>
<h3>prefsGetInt</h3>
<pre><code>int32_t prefsGetInt(PrefsHandleT *h, const char *section, const char *key, int32_t defaultVal);</code></pre>
<p>Retrieve an integer value. Supports decimal and negative numbers.</p>
<pre> Parameter Description
--------- -----------
h Preferences handle
section Section name
key Key name
defaultVal Returned if the key is absent or non-numeric</pre>
<p>Returns: Parsed int, or defaultVal.</p>
<h3>prefsGetBool</h3>
<pre><code>bool prefsGetBool(PrefsHandleT *h, const char *section, const char *key, bool defaultVal);</code></pre>
<p>Retrieve a boolean value. Recognises &quot;true&quot;/&quot;yes&quot;/&quot;1&quot; as true and &quot;false&quot;/&quot;no&quot;/&quot;0&quot; as false (case-insensitive).</p>
<pre> Parameter Description
--------- -----------
h Preferences handle
section Section name
key Key name
defaultVal Returned if the key is absent or unrecognised</pre>
<p>Returns: Parsed bool, or defaultVal.</p>
<h2>Setters</h2>
<h3>prefsSetString</h3>
<pre><code>void prefsSetString(PrefsHandleT *h, const char *section, const char *key, const char *value);</code></pre>
<p>Set a string value. Creates the section and key if they do not already exist.</p>
<h3>prefsSetInt</h3>
<pre><code>void prefsSetInt(PrefsHandleT *h, const char *section, const char *key, int32_t value);</code></pre>
<p>Set an integer value (stored in decimal).</p>
<h3>prefsSetBool</h3>
<pre><code>void prefsSetBool(PrefsHandleT *h, const char *section, const char *key, bool value);</code></pre>
<p>Set a boolean value (stored as &quot;true&quot;/&quot;false&quot;).</p>
<h3>prefsRemove</h3>
<pre><code>void prefsRemove(PrefsHandleT *h, const char *section, const char *key);</code></pre>
<p>Remove a key from a section. No-op if the key does not exist.</p>
</div>
<div class="topic" id="api.mem">
<h1>dvxMem.h -- Per-App Memory Tracking</h1>
<p>Wraps malloc/free/calloc/realloc/strdup with a 16-byte header that records the owning app ID and allocation size. The Task Manager displays per-app memory usage, and leaks are detected when an app is terminated.</p>
<p>DXE code does NOT need to include this header for tracking to work. The DXE export table maps malloc/free/calloc/realloc/strdup to these wrappers transparently. Call sites that need the explicit dvxXxx names (e.g. dvxMemGetAppUsage) or the dvxMemAppIdPtr declaration should include dvxMem.h directly.</p>
<h2>Globals</h2>
<h3>dvxMemAppIdPtr</h3>
<pre><code>extern int32_t *dvxMemAppIdPtr;</code></pre>
<p>Pointer to the current owning app ID. The shell points this at its currentAppId field during init so every allocation is charged to the running app. When dvxMemAppIdPtr is NULL or points to zero, allocations are charged to the shell.</p>
<h2>Allocation Wrappers</h2>
<h3>dvxMalloc</h3>
<pre><code>void *dvxMalloc(size_t size);</code></pre>
<p>Tracked malloc. Returns a pointer to user memory (header is hidden in front of it).</p>
<h3>dvxCalloc</h3>
<pre><code>void *dvxCalloc(size_t nmemb, size_t size);</code></pre>
<p>Tracked calloc.</p>
<h3>dvxRealloc</h3>
<pre><code>void *dvxRealloc(void *ptr, size_t size);</code></pre>
<p>Tracked realloc. Works correctly with tracked pointers only -- the magic header identifies them.</p>
<h3>dvxFree</h3>
<pre><code>void dvxFree(void *ptr);</code></pre>
<p>Tracked free. Falls through to the real free() if the pointer's header magic does not match, so mixing tracked and untracked pointers is safe.</p>
<h3>dvxStrdup</h3>
<pre><code>char *dvxStrdup(const char *s);</code></pre>
<p>Tracked strdup.</p>
<h2>Accounting</h2>
<h3>dvxMemSnapshotLoad</h3>
<pre><code>void dvxMemSnapshotLoad(int32_t appId);</code></pre>
<p>Record a baseline memory snapshot for the given app. Called right before app code starts so later calls to dvxMemGetAppUsage can report net growth.</p>
<pre> Parameter Description
--------- -----------
appId App ID to snapshot</pre>
<h3>dvxMemGetAppUsage</h3>
<pre><code>uint32_t dvxMemGetAppUsage(int32_t appId);</code></pre>
<p>Return the total bytes currently charged to the given app ID.</p>
<pre> Parameter Description
--------- -----------
appId App ID to query</pre>
<p>Returns: Bytes allocated for this app.</p>
<h3>dvxMemResetApp</h3>
<pre><code>void dvxMemResetApp(int32_t appId);</code></pre>
<p>Free every tracked allocation charged to the given app. Called by the shell after an app exits or crashes to reclaim its memory.</p>
<pre> Parameter Description
--------- -----------
appId App ID to flush</pre>
</div>
<div class="topic" id="api.widgetplugin">
<h1>dvxWgtP.h -- Widget Plugin API</h1>
<p>Included by widget .c files (DXE modules) to access core infrastructure for tree manipulation, focus management, scrollbar drawing, layout helpers, and shared interaction state. This header is NOT intended for application code -- use dvxWgt.h for the public widget API.</p>
<h2>Validation Macros</h2>
<h3>VALIDATE_WIDGET / VALIDATE_WIDGET_VOID</h3>
<pre><code>VALIDATE_WIDGET(w, wtype, retval); // returns retval on mismatch
VALIDATE_WIDGET_VOID(w, wtype); // returns void on mismatch</code></pre>
<p>Bail out of a widget method if the widget pointer is NULL or its type does not match the expected wtype. Use at the top of every widget-specific API function.</p>
<h2>Core Constants</h2>
<pre> Define Value Description
------ ----- -----------
DEFAULT_SPACING 4 Default pixel spacing between VBox/HBox children
DEFAULT_PADDING 4 Default internal padding for containers
SB_MIN_THUMB 14 Minimum scrollbar thumb size in pixels
WGT_SB_W 14 Widget-internal scrollbar width
KEY_MOD_SHIFT 0x03 Shift modifier bits
KEY_MOD_CTRL 0x04 Ctrl modifier bit
KEY_MOD_ALT 0x08 Alt modifier bit</pre>
<h2>Inline Helpers</h2>
<h3>clampInt</h3>
<pre><code>static inline int32_t clampInt(int32_t val, int32_t lo, int32_t hi);</code></pre>
<p>Clamp val into the [lo, hi] range.</p>
<h3>drawTextEmbossed</h3>
<pre><code>static inline void drawTextEmbossed(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, const ColorSchemeT *colors);</code></pre>
<p>Draw text twice -- once offset by (1,1) in highlight color, then overlaid in shadow color at (x,y) -- for a classic Motif-style embossed look used on disabled labels.</p>
<h3>drawTextAccelEmbossed</h3>
<pre><code>static inline void drawTextAccelEmbossed(DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, int32_t x, int32_t y, const char *text, const ColorSchemeT *colors);</code></pre>
<p>Embossed text with &amp; accelerator markers. Same offset logic as drawTextEmbossed, but processes &amp; markers.</p>
<h2>Shared Interaction State</h2>
<p>Extern variables defined in widgetCore.c. These hold system-wide widget state: only one focused widget, one open popup, one pressed button at a time.</p>
<pre> Variable Type Purpose
-------- ---- -------
sCursorBlinkOn bool Current state of the text cursor blink
sDblClickTicks clock_t Double-click interval in clock() ticks
sDebugLayout bool When true, draw colored debug borders around containers
sClosedPopup WidgetT* Widget whose popup just closed (suppresses re-open)
sFocusedWidget WidgetT* Currently focused widget
sKeyPressedBtn WidgetT* Button being pressed via keyboard (for release tracking)
sOpenPopup WidgetT* Currently open popup (dropdown/combo list)
sDragWidget WidgetT* Widget being dragged (any drag type)
sPollWidgetCount int32_t Count of widgets with WCLASS_NEEDS_POLL flag set
sPollWidgets WidgetT** Dynamic array of poll widgets (stb_ds)
sCursorBlinkFn fn ptr Callback invoked when the blink flips (repaints focused text)</pre>
<h2>Core Widget Functions</h2>
<h3>widgetAlloc</h3>
<pre><code>WidgetT *widgetAlloc(WidgetT *parent, int32_t type);</code></pre>
<p>Allocate a new WidgetT, initialize its fields to defaults, link it as the last child of parent (if non-NULL), and assign its class pointer from widgetClassTable[type].</p>
<h3>widgetAddChild</h3>
<pre><code>void widgetAddChild(WidgetT *parent, WidgetT *child);</code></pre>
<p>Append child to parent's child list. Updates parent's firstChild/lastChild and child's nextSibling pointers.</p>
<h3>widgetRemoveChild</h3>
<pre><code>void widgetRemoveChild(WidgetT *parent, WidgetT *child);</code></pre>
<p>Unlink child from parent's child list. Does not destroy the child.</p>
<h3>widgetDestroyChildren</h3>
<pre><code>void widgetDestroyChildren(WidgetT *w);</code></pre>
<p>Recursively destroy all descendants of w, calling each one's wclsDestroy handler.</p>
<h2>Focus Management</h2>
<h3>widgetFindNextFocusable</h3>
<pre><code>WidgetT *widgetFindNextFocusable(WidgetT *root, WidgetT *after);</code></pre>
<p>Find the next focusable widget in tab order after the given widget. Wraps to the beginning at the end of the tree.</p>
<h3>widgetFindPrevFocusable</h3>
<pre><code>WidgetT *widgetFindPrevFocusable(WidgetT *root, WidgetT *before);</code></pre>
<p>Find the previous focusable widget in tab order. Wraps to the end at the beginning of the tree.</p>
<h3>widgetFindByAccel</h3>
<pre><code>WidgetT *widgetFindByAccel(WidgetT *root, char key);</code></pre>
<p>Find a focusable widget whose accelKey (lowercase) matches the given character. Used for Alt+letter hotkeys on buttons and labels.</p>
<h2>Hit Testing</h2>
<h3>widgetHitTest</h3>
<pre><code>WidgetT *widgetHitTest(WidgetT *w, int32_t x, int32_t y);</code></pre>
<p>Find the deepest widget at (x, y) within w's subtree. Respects WCLASS_NO_HIT_RECURSE so certain widget types can prevent children from being hit-tested.</p>
<h2>Utility Queries</h2>
<h3>widgetCountVisibleChildren</h3>
<pre><code>int32_t widgetCountVisibleChildren(const WidgetT *w);</code></pre>
<p>Count children whose visible flag is true.</p>
<h3>widgetFrameBorderWidth</h3>
<pre><code>int32_t widgetFrameBorderWidth(const WidgetT *w);</code></pre>
<p>Return the effective border width for a container widget (used to inset child layout).</p>
<h3>widgetIsFocusable</h3>
<pre><code>bool widgetIsFocusable(int32_t type);</code></pre>
<p>True if the widget class with this type ID has the WCLASS_FOCUSABLE flag.</p>
<h3>widgetIsHorizContainer</h3>
<pre><code>bool widgetIsHorizContainer(int32_t type);</code></pre>
<p>True if the widget class lays out children horizontally (WCLASS_HORIZ_CONTAINER).</p>
<h3>multiClickDetect</h3>
<pre><code>int32_t multiClickDetect(int32_t vx, int32_t vy);</code></pre>
<p>Track consecutive clicks at roughly the same position within sDblClickTicks. Returns the current click count (1 for single, 2 for double, etc.).</p>
<h2>Clipboard</h2>
<h3>clipboardCopy</h3>
<pre><code>void clipboardCopy(const char *text, int32_t len);</code></pre>
<p>Copy text to the process-wide clipboard buffer. Same underlying storage as dvxClipboardCopy.</p>
<h3>clipboardGet</h3>
<pre><code>const char *clipboardGet(int32_t *outLen);</code></pre>
<p>Retrieve clipboard text.</p>
<h3>clipboardMaxLen</h3>
<pre><code>int32_t clipboardMaxLen(void);</code></pre>
<p>Return the fixed capacity of the clipboard buffer in bytes.</p>
<h2>Scrollbar Helpers</h2>
<h3>ScrollHitE</h3>
<p>Scrollbar hit-test result.</p>
<pre> Value Description
----- -----------
ScrollHitNoneE Click fell outside the scrollbar
ScrollHitArrowDecE Up/left arrow
ScrollHitArrowIncE Down/right arrow
ScrollHitPageDecE Trough above/before the thumb
ScrollHitPageIncE Trough below/after the thumb
ScrollHitThumbE The draggable thumb</pre>
<h3>widgetScrollbarThumb</h3>
<pre><code>void widgetScrollbarThumb(int32_t trackLen, int32_t totalSize, int32_t visibleSize, int32_t scrollPos, int32_t *thumbPos, int32_t *thumbSize);</code></pre>
<p>Compute thumb position and size for a scrollbar with the given geometry. Enforces SB_MIN_THUMB.</p>
<h3>widgetDrawScrollbarV / widgetDrawScrollbarVEx</h3>
<pre><code>void widgetDrawScrollbarV(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, int32_t sbX, int32_t sbY, int32_t sbH, int32_t totalSize, int32_t visibleSize, int32_t scrollPos);
void widgetDrawScrollbarVEx(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, int32_t sbX, int32_t sbY, int32_t sbH, int32_t totalSize, int32_t visibleSize, int32_t scrollPos, int32_t barW);</code></pre>
<p>Draw a vertical scrollbar inside a widget. The Ex variant lets the caller specify bar width for non-standard scrollbars (e.g. combo popups). Standard variant uses WGT_SB_W.</p>
<h3>widgetDrawScrollbarH / widgetDrawScrollbarHEx</h3>
<pre><code>void widgetDrawScrollbarH(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, int32_t sbX, int32_t sbY, int32_t sbW, int32_t totalSize, int32_t visibleSize, int32_t scrollPos);
void widgetDrawScrollbarHEx(DisplayT *d, const BlitOpsT *ops, const ColorSchemeT *colors, int32_t sbX, int32_t sbY, int32_t sbW, int32_t totalSize, int32_t visibleSize, int32_t scrollPos, int32_t barW);</code></pre>
<p>Draw a horizontal scrollbar inside a widget. Standard variant uses WGT_SB_W.</p>
<h3>widgetScrollbarHitTest</h3>
<pre><code>ScrollHitE widgetScrollbarHitTest(int32_t sbLen, int32_t relPos, int32_t totalSize, int32_t visibleSize, int32_t scrollPos);</code></pre>
<p>Classify a click position along a scrollbar into ScrollHitE. sbLen is the scrollbar length, relPos is the click position along the bar.</p>
<h2>Layout Functions</h2>
<h3>widgetCalcMinSizeBox / widgetCalcMinSizeTree</h3>
<pre><code>void widgetCalcMinSizeBox(WidgetT *w, const BitmapFontT *font);
void widgetCalcMinSizeTree(WidgetT *w, const BitmapFontT *font);</code></pre>
<p>Generic box-container min-size calculation (bottom-up layout pass). widgetCalcMinSizeBox handles a single VBox/HBox; widgetCalcMinSizeTree recurses through the whole subtree.</p>
<h3>widgetLayoutBox / widgetLayoutChildren</h3>
<pre><code>void widgetLayoutBox(WidgetT *w, const BitmapFontT *font);
void widgetLayoutChildren(WidgetT *w, const BitmapFontT *font);</code></pre>
<p>Generic box-container layout (top-down pass). widgetLayoutBox lays out a single container; widgetLayoutChildren processes each child's layout handler.</p>
<h2>Event Dispatch</h2>
<h3>widgetOnPaint / widgetOnMouse / widgetOnKey / etc.</h3>
<pre><code>void widgetOnPaint(WindowT *win, RectT *dirtyArea);
void widgetOnMouse(WindowT *win, int32_t x, int32_t y, int32_t buttons);
void widgetOnKey(WindowT *win, int32_t key, int32_t mod);
void widgetOnKeyUp(WindowT *win, int32_t scancode, int32_t mod);
void widgetOnResize(WindowT *win, int32_t newW, int32_t newH);
void widgetOnScroll(WindowT *win, ScrollbarOrientE orient, int32_t value);
void widgetOnFocus(WindowT *win);
void widgetOnBlur(WindowT *win);</code></pre>
<p>Window-level event handlers that dispatch to individual widgets in the tree. wgtInitWindow installs these as the window's onPaint/onMouse/onKey/etc. callbacks.</p>
<h3>widgetManageScrollbars</h3>
<pre><code>void widgetManageScrollbars(WindowT *win, AppContextT *ctx);</code></pre>
<p>Add, remove, or resize window scrollbars based on the widget tree's current min-size vs. the window content area.</p>
<h2>Paint Helpers</h2>
<h3>widgetPaintOne</h3>
<pre><code>void widgetPaintOne(WidgetT *w, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors);</code></pre>
<p>Paint a single widget (sets clip rect, calls the widget's PAINT handler). Does not recurse.</p>
<h3>widgetPaintOverlays</h3>
<pre><code>void widgetPaintOverlays(WidgetT *root, DisplayT *d, const BlitOpsT *ops, const BitmapFontT *font, const ColorSchemeT *colors);</code></pre>
<p>Paint the overlay pass: dropdown popups and tooltips drawn on top of the main tree.</p>
<h2>Pressable Button Helpers</h2>
<p>Shared state machine for WCLASS_PRESS_RELEASE widgets (Button, ImageButton). The w-&gt;pressed flag tracks the visual state; these helpers fire the widget's onClick callback on release-within-bounds.</p>
<h3>widgetPressableOnMouse / widgetPressableOnKey / widgetPressableOnDragUpdate / widgetPressableOnDragEnd / widgetPressableOnAccelActivate</h3>
<pre><code>void widgetPressableOnMouse(WidgetT *w, WidgetT *root, int32_t vx, int32_t vy);
void widgetPressableOnKey(WidgetT *w, int32_t key, int32_t mod);
void widgetPressableOnDragUpdate(WidgetT *w, WidgetT *root, int32_t x, int32_t y);
void widgetPressableOnDragEnd(WidgetT *w, WidgetT *root, int32_t x, int32_t y);
void widgetPressableOnAccelActivate(WidgetT *w, WidgetT *root);</code></pre>
<p>Register these directly as the widget class's handlers for WGT_METHOD_ON_MOUSE, WGT_METHOD_ON_KEY, WGT_METHOD_ON_DRAG_UPDATE, WGT_METHOD_ON_DRAG_END, and WGT_METHOD_ON_ACCEL_ACTIVATE.</p>
<h2>Generic Text Handlers</h2>
<p>For widgets whose data struct has a (const char *) as its first field and the WCLASS_HAS_TEXT flag set, these implement GET_TEXT / SET_TEXT directly.</p>
<h3>widgetTextGet / widgetTextSet</h3>
<pre><code>const char *widgetTextGet(const WidgetT *w);
void widgetTextSet(WidgetT *w, const char *text);</code></pre>
<p>Register these directly as the widget class's handlers for WGT_METHOD_GET_TEXT and WGT_METHOD_SET_TEXT. The text is strdup'd on set and freed automatically on destroy.</p>
<h2>Class Table</h2>
<h3>widgetClassTable</h3>
<pre><code>extern const WidgetClassT **widgetClassTable;</code></pre>
<p>stb_ds dynamic array. Each widget DXE appends its class pointer via wgtRegisterClass() during wgtRegister(). Indexed by the runtime type ID assigned at registration.</p>
</div>
<div class="topic" id="api.platform">
<h1>platform/dvxPlat.h -- Platform Abstraction Layer</h1>
<p>All OS-specific and CPU-specific code is isolated behind this interface. Port DVX to a new platform by implementing a new dvxPlatformXxx.c against this header. Currently the only implementation is dvxPlatformDos.c for DJGPP/DPMI.</p>
<p>Platform functions must be stateless (or manage their own internal state) and must not reference AppContextT or any layer above dvxTypes.h.</p>
<h2>Constants</h2>
<pre> Define Value Description
------ ----- -----------
DVX_MAX_PATH 260 Maximum file path length
PLATFORM_SYSINFO_MAX 4096 Maximum size of formatted system info text
DVX_PATH_SEP &quot;\\&quot; Native directory separator on DOS</pre>
<h2>Types</h2>
<h3>PlatformKeyEventT</h3>
<p>Keyboard event with ASCII and scancode separated. Extended keys (arrows, F-keys) have ascii == 0 and a non-zero scancode.</p>
<pre> Field Description
----- -----------
ascii ASCII value, 0 for extended/function keys
scancode PC scancode (e.g. 0x48 = Up, 0x50 = Down)</pre>
<h3>PlatformLogFnT</h3>
<pre><code>typedef void (*PlatformLogFnT)(const char *fmt, ...);</code></pre>
<p>Log function signature used by the crash handler.</p>
<h3>PlatformSymOverrideT</h3>
<p>Name/function-pointer pair for registering symbol overrides with the DXE loader.</p>
<pre> Field Description
----- -----------
name Symbol name as seen by DXEs
func Function pointer to use instead of the default</pre>
<h2>Lifecycle</h2>
<h3>dvxLog</h3>
<pre><code>void dvxLog(const char *fmt, ...);</code></pre>
<p>Append a formatted line to dvx.log. Implemented in dvx.exe and exported to every DXE via the loader.</p>
<h3>platformInit</h3>
<pre><code>void platformInit(void);</code></pre>
<p>One-time platform initialization. On DOS this installs signal handlers for clean shutdown on Ctrl+C/Ctrl+Break.</p>
<h3>platformYield</h3>
<pre><code>void platformYield(void);</code></pre>
<p>Cooperative CPU yield, used between frames when the event loop has nothing to do. On DOS this calls __dpmi_yield() to be friendly to multitaskers.</p>
<h2>Video</h2>
<h3>platformVideoInit / platformVideoShutdown</h3>
<pre><code>int32_t platformVideoInit(DisplayT *d, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);
void platformVideoShutdown(DisplayT *d);</code></pre>
<p>Low-level video mode setup and teardown. Called by videoInit / videoShutdown.</p>
<h3>platformVideoEnumModes</h3>
<pre><code>void platformVideoEnumModes(void (*cb)(int32_t w, int32_t h, int32_t bpp, void *userData), void *userData);</code></pre>
<p>Enumerate LFB-capable graphics modes. Invokes cb once per available mode.</p>
<h3>platformVideoSetPalette</h3>
<pre><code>void platformVideoSetPalette(const uint8_t *pal, int32_t firstEntry, int32_t count);</code></pre>
<p>Program the VGA/VESA DAC palette registers (8-bit mode only).</p>
<h3>platformVideoFreeBuffers</h3>
<pre><code>void platformVideoFreeBuffers(DisplayT *d);</code></pre>
<p>Free the backbuffer and palette without restoring text mode. Used when switching between graphics modes live.</p>
<h2>Framebuffer Flush</h2>
<h3>platformFlushRect</h3>
<pre><code>void platformFlushRect(const DisplayT *d, const RectT *r);</code></pre>
<p>Copy a rectangle from the system RAM backbuffer to the LFB. The single critical path where PCI bus write speed matters. On DOS, each scanline uses rep movsd for aligned 32-bit writes.</p>
<h2>Span Operations</h2>
<h3>platformSpanFill8/16/32</h3>
<pre><code>void platformSpanFill8(uint8_t *dst, uint32_t color, int32_t count);
void platformSpanFill16(uint8_t *dst, uint32_t color, int32_t count);
void platformSpanFill32(uint8_t *dst, uint32_t color, int32_t count);</code></pre>
<p>Fill count pixels at dst with color. Three depth variants because the fill instruction differs by size. On DOS these use inline rep stosl / rep stosw / rep stosb asm.</p>
<h3>platformSpanCopy8/16/32</h3>
<pre><code>void platformSpanCopy8(uint8_t *dst, const uint8_t *src, int32_t count);
void platformSpanCopy16(uint8_t *dst, const uint8_t *src, int32_t count);
void platformSpanCopy32(uint8_t *dst, const uint8_t *src, int32_t count);</code></pre>
<p>Copy count pixels from src to dst. On DOS these use rep movsd.</p>
<h2>Mouse Input</h2>
<h3>platformMouseInit</h3>
<pre><code>void platformMouseInit(int32_t screenW, int32_t screenH);</code></pre>
<p>Initialize the mouse driver and constrain movement to the screen bounds.</p>
<h3>platformMousePoll</h3>
<pre><code>void platformMousePoll(int32_t *mx, int32_t *my, int32_t *buttons);</code></pre>
<p>Poll current mouse state. Buttons is a bitmask: bit 0 = left, bit 1 = right, bit 2 = middle.</p>
<h3>platformMouseWheelInit / platformMouseWheelPoll</h3>
<pre><code>bool platformMouseWheelInit(void);
int32_t platformMouseWheelPoll(void);</code></pre>
<p>Detect and activate the CuteMouse Wheel API. platformMouseWheelPoll returns the accumulated delta (positive = scroll down) since the last poll.</p>
<h3>platformMouseSetAccel / platformMouseSetMickeys</h3>
<pre><code>void platformMouseSetAccel(int32_t threshold);
void platformMouseSetMickeys(int32_t horizMickeys, int32_t vertMickeys);</code></pre>
<p>Set the double-speed threshold and mickey-to-pixel ratio. See dvxSetMouseConfig for a higher-level interface.</p>
<h3>platformMouseWarp</h3>
<pre><code>void platformMouseWarp(int32_t x, int32_t y);</code></pre>
<p>Move the mouse cursor to an absolute screen position. Used to clamp the cursor to window edges during resize.</p>
<h2>Keyboard Input</h2>
<h3>platformKeyboardGetModifiers</h3>
<pre><code>int32_t platformKeyboardGetModifiers(void);</code></pre>
<p>Return the current modifier key state in BIOS shift-state format.</p>
<h3>platformKeyboardRead</h3>
<pre><code>bool platformKeyboardRead(PlatformKeyEventT *evt);</code></pre>
<p>Non-blocking read of the next key from the keyboard buffer. Returns true if a key was available.</p>
<h3>platformKeyUpInit / platformKeyUpShutdown / platformKeyUpRead</h3>
<pre><code>void platformKeyUpInit(void);
void platformKeyUpShutdown(void);
bool platformKeyUpRead(PlatformKeyEventT *evt);</code></pre>
<p>Key-up event detection. Install/uninstall the INT 9 hook around process lifetime. platformKeyUpRead returns true if a key release was detected since the last call.</p>
<h3>platformAltScanToChar</h3>
<pre><code>char platformAltScanToChar(int32_t scancode);</code></pre>
<p>Translate an Alt+key scancode to its corresponding ASCII character. Returns 0 for non-printable scancodes.</p>
<h2>System Information</h2>
<h3>platformGetSystemInfo</h3>
<pre><code>const char *platformGetSystemInfo(const DisplayT *display);</code></pre>
<p>Return a pre-formatted text string with hardware/OS information (CPU, clock, memory, video, mouse, disks). Valid for the lifetime of the process.</p>
<h3>platformGetMemoryInfo</h3>
<pre><code>bool platformGetMemoryInfo(uint32_t *totalKb, uint32_t *freeKb);</code></pre>
<p>Query total and free physical memory.</p>
<h2>File System</h2>
<h3>platformValidateFilename</h3>
<pre><code>const char *platformValidateFilename(const char *name);</code></pre>
<p>Validate a filename against platform-specific rules (8.3 on DOS). Returns NULL if valid, or a human-readable error string.</p>
<h3>platformMkdirRecursive</h3>
<pre><code>int32_t platformMkdirRecursive(const char *path);</code></pre>
<p>Create a directory and all parent directories (like mkdir -p). Existing directories are not an error.</p>
<h3>platformChdir</h3>
<pre><code>int32_t platformChdir(const char *path);</code></pre>
<p>Change the working directory, including drive letter on DOS (calls setdisk() first when the path starts with &quot;X:&quot;).</p>
<h3>platformPathDirEnd</h3>
<pre><code>char *platformPathDirEnd(const char *path);</code></pre>
<p>Return a pointer to the last directory separator in path, or NULL. On DOS accepts both &quot;/&quot; and &quot;\\&quot;.</p>
<h3>platformPathBaseName</h3>
<pre><code>const char *platformPathBaseName(const char *path);</code></pre>
<p>Return a pointer to the leaf (basename) portion of path.</p>
<h3>platformReadFile</h3>
<pre><code>char *platformReadFile(const char *path, int32_t *outLen);</code></pre>
<p>Slurp a whole file into a freshly malloc'd, NUL-terminated buffer. Caller frees. Binary-safe: the NUL is past the end of the reported length.</p>
<h3>platformGlobMatch</h3>
<pre><code>bool platformGlobMatch(const char *pattern, const char *name);</code></pre>
<p>Simple glob pattern match. Case-insensitive. Supports * (zero or more chars) and ? (single char).</p>
<h3>platformLineEnding / platformStripLineEndings</h3>
<pre><code>const char *platformLineEnding(void);
int32_t platformStripLineEndings(char *buf, int32_t len);</code></pre>
<p>Return the native line ending string, or strip line-ending characters from a buffer in place.</p>
<h2>String Helpers</h2>
<h3>dvxSkipWs</h3>
<pre><code>const char *dvxSkipWs(const char *s);</code></pre>
<p>Advance past leading spaces and tabs. Returns s unchanged if NULL or already non-whitespace.</p>
<h3>dvxTrimRight</h3>
<pre><code>int32_t dvxTrimRight(char *buf);</code></pre>
<p>Strip trailing spaces, tabs, carriage returns, and newlines from buf in place. Returns the new length.</p>
<h2>DXE Module Support</h2>
<h3>platformRegisterDxeExports</h3>
<pre><code>void platformRegisterDxeExports(void);</code></pre>
<p>Register platform and C runtime symbols with the dynamic module loader so DXE modules can resolve them at load time.</p>
<h3>platformRegisterSymOverrides</h3>
<pre><code>void platformRegisterSymOverrides(const PlatformSymOverrideT *entries);</code></pre>
<p>Register function pointer overrides for subsequently loaded modules. entries is terminated by {NULL, NULL}.</p>
<h2>Crash Recovery</h2>
<h3>platformInstallCrashHandler</h3>
<pre><code>void platformInstallCrashHandler(jmp_buf *recoveryBuf, volatile int *crashSignal, PlatformLogFnT logFn);</code></pre>
<p>Install signal handlers for SIGSEGV, SIGFPE, SIGILL. On crash, logs platform-specific diagnostics via logFn, stores the signal in *crashSignal, then longjmps to recoveryBuf.</p>
<h3>platformLogCrashDetail</h3>
<pre><code>void platformLogCrashDetail(int sig, PlatformLogFnT logFn);</code></pre>
<p>Log platform-specific crash diagnostics. Called internally from the crash handler and exposed for manual invocation.</p>
<h2>VGA Splash Screen</h2>
<h3>platformSplashInit / platformSplashShutdown</h3>
<pre><code>void platformSplashInit(void);
void platformSplashShutdown(void);</code></pre>
<p>Enter/leave VGA mode 13h (320x200x256) used for the boot splash.</p>
<h3>platformSplashLoadRaw</h3>
<pre><code>bool platformSplashLoadRaw(const char *path);</code></pre>
<p>Load and display a raw splash file (768-byte palette + 64000-byte pixel data).</p>
<h3>platformSplashFillRect</h3>
<pre><code>void platformSplashFillRect(int32_t x, int32_t y, int32_t w, int32_t h, uint8_t color);</code></pre>
<p>Fill a rectangle on the mode 13h screen with a palette index. Used to draw the progress bar during module loading.</p>
</div>
<div class="topic" id="libtasks">
<h1>libtasks -- Cooperative Task Switching</h1>
<p>Credit-based cooperative (non-preemptive) multitasking library for DOS protected mode (DJGPP/DPMI). Each task receives (priority + 1) credits per scheduling round. Tasks run round-robin, consuming one credit per turn. When all credits are exhausted, every ready task is refilled. Higher-priority tasks run proportionally more often but never starve lower ones.</p>
<p>Header: libtasks/taskSwch.h</p>
<p>Loaded as: bin/libs/libtasks.lib</p>
<h2>Why Cooperative</h2>
<p>DOS is single-threaded with no kernel scheduler. DPMI provides no preemption primitives. The DVX GUI event model is inherently single-threaded: one compositor, one input queue, one window stack. Cooperative switching lets each task yield at safe points, avoiding synchronization primitives entirely.</p>
<h2>Scheduling Semantics</h2>
<p>Task storage is a stb_ds dynamic array. Terminated slots are recycled by tsCreate so the array does not grow unboundedly. The scheduler performs a linear scan for the next Ready task whose credit count is positive; when no task has credits left, every Ready task is refilled with (priority + 1) credits and the scan restarts.</p>
<pre> Priority Credits per round Approximate share
-------- ----------------- -----------------
TS_PRIORITY_LOW 1 ~4% (1 of 25 possible credits)
TS_PRIORITY_NORMAL 6 ~22%
TS_PRIORITY_HIGH 11 ~41%</pre>
<p>Actual share depends on the mix of priorities currently running. What the algorithm guarantees is that no ready task ever goes unscheduled -- even a priority-0 task always earns at least one turn per round.</p>
<h3>Stack Allocation</h3>
<p>Task 0 uses the caller's stack (no separate allocation). Every other task gets a heap-allocated stack of the size passed to tsCreate (or TS_DEFAULT_STACK_SIZE if 0 is passed). Stacks are freed at task termination, either via tsExit or tsKill.</p>
<h2>Error Codes</h2>
<pre> Constant Value Description
-------- ----- -----------
TS_OK 0 Success
TS_ERR_INIT -1 Task system not initialized
TS_ERR_PARAM -2 Invalid parameter (bad task ID, etc.)
TS_ERR_FULL -3 Task array full (should not occur; array grows)
TS_ERR_NOMEM -4 Memory allocation failed
TS_ERR_STATE -5 Invalid state transition</pre>
<h2>Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
TS_DEFAULT_STACK_SIZE 32768 Default stack size per task (32 KB)
TS_NAME_MAX 32 Maximum task name length including NUL
TS_PRIORITY_LOW 0 Low priority (1 credit per round)
TS_PRIORITY_NORMAL 5 Normal priority (6 credits per round)
TS_PRIORITY_HIGH 10 High priority (11 credits per round)</pre>
<h2>Types</h2>
<h3>TaskStateE</h3>
<p>Task scheduling state. Only Ready tasks participate in scheduling.</p>
<pre> Value Description
----- -----------
TaskStateReady Eligible for scheduling
TaskStateRunning Currently executing (cosmetic; marks active task)
TaskStatePaused Skipped by scheduler until explicitly resumed
TaskStateTerminated Slot available for reuse</pre>
<h3>TaskEntryT</h3>
<pre><code>typedef void (*TaskEntryT)(void *arg);</code></pre>
<p>Task entry point function signature. The void* argument lets the caller pass arbitrary context (e.g. a shell app descriptor).</p>
<h2>tsInit</h2>
<pre><code>int32_t tsInit(void);</code></pre>
<p>Initialize the task system. The calling context becomes task 0 (the main task). Task 0 is special: it cannot be killed or paused, and tsRecoverToMain() always returns control here. No separate stack is allocated for task 0; it uses the process stack directly.</p>
<p>Returns: TS_OK on success, TS_ERR_PARAM if already initialized.</p>
<h2>tsShutdown</h2>
<pre><code>void tsShutdown(void);</code></pre>
<p>Shut down the task system and free all task stacks and internal storage. Safe to call even if tsInit() was never called.</p>
<h2>tsCreate</h2>
<pre><code>int32_t tsCreate(const char *name, TaskEntryT entry, void *arg, uint32_t stackSize, int32_t priority);</code></pre>
<p>Create a new task. Terminated task slots are recycled to avoid unbounded array growth.</p>
<pre> Parameter Description
--------- -----------
name Task name (truncated to TS_NAME_MAX - 1 characters)
entry Task entry point function
arg Opaque argument passed to entry
stackSize Stack size in bytes (pass 0 for TS_DEFAULT_STACK_SIZE)
priority Scheduling priority (0..10; use TS_PRIORITY_* constants)</pre>
<p>Returns: Task ID (&gt;= 0) on success, or a negative error code (TS_ERR_PARAM if not initialized or entry is NULL, TS_ERR_NOMEM if stack allocation failed).</p>
<h2>tsYield</h2>
<pre><code>void tsYield(void);</code></pre>
<p>Yield CPU to the next eligible ready task using credit-based round-robin. This is the sole mechanism for task switching. Every task must call this (or a GUI function that calls it) periodically, or it will monopolize the CPU.</p>
<h2>tsPause</h2>
<pre><code>int32_t tsPause(uint32_t taskId);</code></pre>
<p>Pause a task, removing it from scheduling. Cannot pause the main task (ID 0). If a task pauses itself, an implicit yield occurs.</p>
<pre> Parameter Description
--------- -----------
taskId ID of the task to pause</pre>
<p>Returns: TS_OK on success, TS_ERR_PARAM on invalid ID, or TS_ERR_STATE if the task is the main task or not in a pausable state (not Running or Ready).</p>
<h2>tsResume</h2>
<pre><code>int32_t tsResume(uint32_t taskId);</code></pre>
<p>Resume a paused task. Credits are refilled so the task gets a fair share of CPU time immediately rather than waiting for the next scheduling round.</p>
<pre> Parameter Description
--------- -----------
taskId ID of the task to resume</pre>
<p>Returns: TS_OK on success, TS_ERR_PARAM on invalid ID, TS_ERR_STATE if the task is not paused.</p>
<h2>tsSetPriority</h2>
<pre><code>int32_t tsSetPriority(uint32_t taskId, int32_t priority);</code></pre>
<p>Set a task's scheduling priority. Also refills credits so the change takes effect immediately.</p>
<pre> Parameter Description
--------- -----------
taskId ID of the task to modify
priority New priority level (0..10)</pre>
<p>Returns: TS_OK on success, TS_ERR_PARAM on invalid ID, or TS_ERR_STATE if the task is terminated.</p>
<h2>tsGetPriority</h2>
<pre><code>int32_t tsGetPriority(uint32_t taskId);</code></pre>
<p>Get a task's current scheduling priority.</p>
<pre> Parameter Description
--------- -----------
taskId ID of the task to query</pre>
<p>Returns: Priority value (0..10) on success, TS_ERR_PARAM on invalid ID.</p>
<h2>tsGetState</h2>
<pre><code>TaskStateE tsGetState(uint32_t taskId);</code></pre>
<p>Get a task's current scheduling state.</p>
<pre> Parameter Description
--------- -----------
taskId ID of the task to query</pre>
<p>Returns: TaskStateE value. Returns TaskStateTerminated for invalid IDs.</p>
<h2>tsCurrentId</h2>
<pre><code>uint32_t tsCurrentId(void);</code></pre>
<p>Get the ID of the currently executing task. Always valid while the task system is initialized.</p>
<p>Returns: Current task ID.</p>
<h2>tsGetName</h2>
<pre><code>const char *tsGetName(uint32_t taskId);</code></pre>
<p>Get a task's name string.</p>
<pre> Parameter Description
--------- -----------
taskId ID of the task to query</pre>
<p>Returns: Pointer to the task's name, or NULL on invalid ID. The pointer remains valid until the task slot is reused.</p>
<h2>tsExit</h2>
<pre><code>void tsExit(void);</code></pre>
<p>Terminate the calling task. Must not be called from the main task (ID 0). The stack is freed immediately and the slot is marked for reuse. This function never returns; it performs an internal context switch to the next ready task.</p>
<h2>tsKill</h2>
<pre><code>int32_t tsKill(uint32_t taskId);</code></pre>
<p>Forcibly terminate another task. Cannot kill the main task (ID 0) or the currently running task (use tsExit() for self-termination). Safe because cooperative scheduling guarantees the target is suspended at a yield point.</p>
<pre> Parameter Description
--------- -----------
taskId ID of the task to terminate</pre>
<p>Returns: TS_OK on success, TS_ERR_PARAM on invalid ID, or TS_ERR_STATE on illegal target (main task, self, or already terminated).</p>
<h2>tsRecoverToMain</h2>
<pre><code>void tsRecoverToMain(void);</code></pre>
<p>Crash recovery: force the scheduler back to the main task (ID 0). Call after longjmp from a signal handler that fired in a non-main task. The crashed task is NOT cleaned up by this call; call tsKill() afterward to free its resources. This exists because longjmp unwinds the crashed task's stack but the scheduler state still points to it.</p>
<h2>tsActiveCount</h2>
<pre><code>uint32_t tsActiveCount(void);</code></pre>
<p>Get the number of non-terminated tasks currently in the system.</p>
<p>Returns: Count of tasks in Ready, Running, or Paused state.</p>
</div>
<div class="topic" id="shell.overview">
<h1>DVX Shell Library</h1>
<p>The DVX shell library manages the lifecycle of DXE applications: loading, launching, tracking, and reaping. It provides the bridge between the DVX GUI compositor and dynamically loaded DXE3 application modules.</p>
<p>Header: dvxshell/shellApp.h</p>
<p>Loaded as: bin/libs/dvxshell.lib</p>
<h2>App Model</h2>
<p>The shell supports two kinds of DXE apps:</p>
<ul>
<li>Callback-only (hasMainLoop = false) -- appMain() runs in the shell's task 0, creates windows, registers event callbacks, and returns immediately. The app lives through GUI callbacks. Lifecycle ends when the last window is closed. Simpler and cheaper (no extra stack/task).</li>
</ul>
<p>Main-loop (hasMainLoop = true) -- A dedicated cooperative task is created. appMain() runs in that task and can do its own polling loop, calling tsYield() to share CPU. Lifecycle ends when appMain() returns or the task is killed. Needed for terminal emulators, games, or long computations.</p>
<p>Both types use the same DXE interface: an exported appDescriptor and appMain function.</p>
<h2>DXE Interface</h2>
<p>Every .app DXE module must export these symbols (COFF convention uses leading underscore):</p>
<pre> Symbol Type Required
------ ---- --------
_appDescriptor AppDescriptorT Yes
_appMain int32_t (*)(DxeAppContextT *) Yes
_appShutdown void (*)(void) No</pre>
<p>The shell resolves appDescriptor at dlopen time; if missing, the load fails with an error dialog. appMain is called immediately for callback-only apps or from the new task for main-loop apps. appShutdown, if present, is called during graceful reap (but not during force kill from crashed apps).</p>
<h2>Callback-Only vs Main-Loop Apps</h2>
<p>The app descriptor's hasMainLoop flag selects between two very different lifecycles:</p>
<ul>
<li>hasMainLoop = false (callback-only). The shell calls appMain directly on task 0 at dlopen time. The function creates windows, registers event callbacks, and returns. After that the app has no executing thread of its own -- it exists purely through GUI callbacks dispatched by dvxUpdate. The shell reaps the app automatically when its last window closes. Best for modal tools, dialogs, and event-driven utilities.</li>
</ul>
<p>hasMainLoop = true (main-loop). The shell creates a dedicated cooperative task (via tsCreate) with the descriptor's stackSize (or TS_DEFAULT_STACK_SIZE) and priority. appMain runs in that task and can do its own work loop, calling tsYield or any GUI function that yields. The app terminates when appMain returns (the wrapper sets AppStateTerminatingE) or when forced via shellForceKillApp. Best for terminal emulators, games, and any app with continuous background work.</p>
<p>Both app types use the same export interface; only the descriptor's flags differ. Apps cannot switch modes at runtime.</p>
<h2>Icon Conventions</h2>
<p>Shell-level UI (Program Manager, Task Manager) displays app icons at 16x16 and 32x32. Icons are not handled by the shell itself; each app embeds its own icons via the DVX resource system (DVX_RES_ICON):</p>
<ul>
<li>16x16 BMP for toolbar entries and list rows</li>
</ul>
<p>32x32 BMP for desktop shortcuts and Program Manager tiles</p>
<p>The Program Manager reads the app's 32x32 icon resource when building shortcut tiles. Apps without an icon resource fall back to a default shell-provided bitmap.</p>
<h2>State Machine</h2>
<p>App slots progress through four states:</p>
<pre><code>Free -&gt; Loaded -&gt; Running -&gt; Terminating -&gt; Free</code></pre>
<p>LoadedE is transient (only during shellLoadApp before the entry point is called). TerminatingE means the app's task has exited but cleanup has not yet occurred. The shell's main loop reaps terminating apps each frame via shellReapApps().</p>
<h2>Contents</h2>
<p><a href="#shell.types">Types and Constants</a></p>
<p><a href="#shell.lifecycle">Lifecycle API</a></p>
<p><a href="#shell.query">Query API</a></p>
<p><a href="#shell.config">Configuration API</a></p>
<p><a href="#shell.desktop">Desktop Callbacks</a></p>
<p><a href="#shell.info">System Information</a></p>
</div>
<div class="topic" id="shell.types">
<h1>Types and Constants</h1>
<h2>Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
SHELL_APP_NAME_MAX 64 Maximum length of an app name string.
SHELL_STACK_DEFAULT 0 Use in AppDescriptorT.stackSize to get the default task stack size.
SHELL_DESKTOP_APP &quot;apps/kpunch/progman/progman.app&quot; Default desktop application path.</pre>
<h2>AppDescriptorT</h2>
<p>Exported by every DXE app as a global named appDescriptor. The shell reads it at load time to determine how to launch the app.</p>
<pre> Field Type Description
----- ---- -----------
name[SHELL_APP_NAME_MAX] char[] Display name of the application.
hasMainLoop bool false = callback-only, true = dedicated task.
multiInstance bool true = allow multiple simultaneous instances via temp copy.
stackSize int32_t SHELL_STACK_DEFAULT or explicit byte count for the task stack.
priority int32_t TS_PRIORITY_* value or custom priority for the task.</pre>
<h2>DxeAppContextT</h2>
<p>Passed as the sole argument to appMain(). Gives the app access to the shell's GUI context and its own identity. Heap-allocated by shellLoadApp so its address is stable across reallocations of the internal app slot table (apps may safely cache the pointer in their static globals).</p>
<pre> Field Type Description
----- ---- -----------
shellCtx AppContextT * The shell's GUI context (for creating windows, drawing, etc.).
appId int32_t This app's unique ID (slot index, 1-based).
appPath[DVX_MAX_PATH] char[] Full path to the .app DXE file.
appDir[DVX_MAX_PATH] char[] Directory containing the .app file (for loading resources).
configDir[DVX_MAX_PATH] char[] Writable config directory (e.g. CONFIG/APPS/KPUNCH/DVXBASIC/).
args[1024] char[] Launch arguments (empty string if none).
helpFile[DVX_MAX_PATH] char[] Help file path (for F1 context help).
helpTopic[128] char[] Current help topic ID (updated by the app at runtime).
onHelpQuery void (*)(void *ctx) Optional callback the shell fires on F1 so the app can refresh helpTopic from context.
helpQueryCtx void * Opaque context pointer passed to onHelpQuery.</pre>
<p>The appDir field is derived from the .app file path at load time so apps can find their own resources via relative paths. This is necessary because the working directory is shared by all apps in DOS. The config directory is mirrored from the app path: an app at APPS/KPUNCH/DVXBASIC/dvxbasic.app gets CONFIG/APPS/KPUNCH/DVXBASIC/.</p>
<h2>AppStateE</h2>
<pre> Value Description
----- -----------
AppStateFreeE Slot is available for reuse.
AppStateLoadedE DXE loaded, entry point not yet called (transient).
AppStateRunningE Entry point called, app is active.
AppStateTerminatingE Shutdown in progress, awaiting reap.</pre>
<h2>ShellAppT</h2>
<p>Per-app slot in the shell's app table. Slot 0 is reserved for the shell itself; apps use slots 1 and above.</p>
<pre> Field Type Description
----- ---- -----------
appId int32_t Unique ID (slot index, 1-based; 0 = shell).
name[SHELL_APP_NAME_MAX] char[] Display name from AppDescriptorT.
path[DVX_MAX_PATH] char[] Original DXE file path.
tempPath[DVX_MAX_PATH] char[] Temp copy path for multi-instance (empty if not a copy).
dxeHandle void * dlopen() handle for the DXE module.
state AppStateE Current lifecycle state.
hasMainLoop bool Whether this app has a dedicated task.
mainTaskId uint32_t Task ID if hasMainLoop, else 0.
entryFn int32_t (*)(DxeAppContextT *) Pointer to appMain.
shutdownFn void (*)(void) Pointer to appShutdown (may be NULL).
dxeCtx DxeAppContextT * Heap-allocated context (address stable across realloc).</pre>
</div>
<div class="topic" id="shell.lifecycle">
<h1>App Lifecycle API</h1>
<h2>shellAppInit</h2>
<pre><code>void shellAppInit(void);</code></pre>
<p>Initialize the app slot table. Seeds slot 0 (reserved for the shell). Must be called once at startup before any other shell API function.</p>
<h2>shellLoadApp</h2>
<pre><code>int32_t shellLoadApp(AppContextT *ctx, const char *path);</code></pre>
<p>Load and start an app from a DXE file. Returns the app ID (&gt;= 1) on success, or -1 on error.</p>
<p>For callback-only apps, appMain() runs synchronously and returns before shellLoadApp returns. For main-loop apps, a cooperative task is created and the app begins running on the next tsYield().</p>
<p>If multiInstance is false in the app's descriptor and the same DXE is already loaded, the call fails with an error dialog. If multiInstance is true, the DXE is copied to a temp file so dlopen gets an independent code and data image.</p>
<h2>shellLoadAppWithArgs</h2>
<pre><code>int32_t shellLoadAppWithArgs(AppContextT *ctx, const char *path, const char *args);</code></pre>
<p>Load and run an app with arguments. The args string is copied into DxeAppContextT.args before appMain() is called. Otherwise identical to shellLoadApp().</p>
<h2>shellReapApps</h2>
<pre><code>bool shellReapApps(AppContextT *ctx);</code></pre>
<p>Scan for and reap finished apps. Call once per frame from the main loop.</p>
<p>Returns true if any apps were reaped, so the caller can trigger a desktop refresh. For main-loop apps, termination is detected by the AppStateTerminatingE state (set when appMain returns). For callback-only apps, termination is detected when no windows remain for that app.</p>
<h2>shellReapApp</h2>
<pre><code>void shellReapApp(AppContextT *ctx, ShellAppT *app);</code></pre>
<p>Gracefully shut down a single app. Calls the app's shutdownFn (if present), destroys all windows belonging to the app, kills its task (if any), closes the DXE handle, and frees the context. The slot returns to AppStateFreeE.</p>
<h2>shellForceKillApp</h2>
<pre><code>void shellForceKillApp(AppContextT *ctx, ShellAppT *app);</code></pre>
<p>Forcibly kill an app. Used by the Task Manager &quot;End Task&quot; or as part of crash recovery. Calls the app's shutdownFn (if present) so it can unregister callbacks before its DXE is unmapped, then destroys all of the app's windows, kills its task (for main-loop apps), and finally closes the DXE handle.</p>
<p>Cleanup order: shutdownFn first (so the app can unregister callbacks while still mapped), then windows (removes from compositor), then task (frees stack), then DXE handle (unmaps code). Closing the DXE before destroying windows would cause callbacks into unmapped code.</p>
<h2>shellTerminateAllApps</h2>
<pre><code>void shellTerminateAllApps(AppContextT *ctx);</code></pre>
<p>Force-kill all running apps. Called during shell shutdown. Iterates all slots and calls shellForceKillApp() on each active app.</p>
</div>
<div class="topic" id="shell.query">
<h1>Query API</h1>
<h2>shellGetApp</h2>
<pre><code>ShellAppT *shellGetApp(int32_t appId);</code></pre>
<p>Look up an app slot by ID. Returns a pointer to the ShellAppT, or NULL if the ID is out of range or the slot is free. Valid app IDs are 1 through shellAppSlotCount() - 1.</p>
<h2>shellAppSlotCount</h2>
<pre><code>int32_t shellAppSlotCount(void);</code></pre>
<p>Return the total number of app slots (including slot 0). Use as the iteration bound when scanning all slots. Slot 0 is the shell itself; app slots start at 1.</p>
<h2>shellRunningAppCount</h2>
<pre><code>int32_t shellRunningAppCount(void);</code></pre>
<p>Count running apps, not counting the shell itself. Includes apps in both AppStateLoadedE and AppStateRunningE states.</p>
</div>
<div class="topic" id="shell.config">
<h1>Configuration API</h1>
<p>Each app has a per-app configuration directory derived from its DXE path, mirrored under CONFIG/. For example, an app at APPS/KPUNCH/DVXBASIC/dvxbasic.app gets the config directory CONFIG/APPS/KPUNCH/DVXBASIC/.</p>
<h2>shellEnsureConfigDir</h2>
<pre><code>int32_t shellEnsureConfigDir(const DxeAppContextT *ctx);</code></pre>
<p>Ensure the app's config directory exists, creating all parent directories as needed. Returns 0 on success, -1 on failure.</p>
<p>Call this before writing any config files. The directory path comes from ctx-&gt;configDir.</p>
<h2>shellConfigPath</h2>
<pre><code>void shellConfigPath(const DxeAppContextT *ctx, const char *filename, char *outPath, int32_t outSize);</code></pre>
<p>Build a full path to a file in the app's config directory by joining ctx-&gt;configDir with the given filename.</p>
<pre><code>// Example:
char path[DVX_MAX_PATH];
shellConfigPath(ctx, &quot;settings.ini&quot;, path, sizeof(path));
// -&gt; &quot;CONFIG/APPS/KPUNCH/PROGMAN/settings.ini&quot;</code></pre>
</div>
<div class="topic" id="shell.desktop">
<h1>Desktop Callbacks</h1>
<p>The shell wires several AppContextT event hooks (onCtrlEsc, onF1, onTitleChange, idleCallback) during startup and exposes them to other DXEs via function-pointer extern and registration API. Desktop managers register a callback to refresh their display when apps come and go. The Task Manager DXE registers its Ctrl+Esc handler via the shellCtrlEscFn extern pointer (see Task Manager documentation).</p>
<h2>Shell Event Hooks</h2>
<pre> AppContextT field Handler Purpose
----------------- ------- -------
idleCallback idleYield Yields to cooperative tasks when dvxUpdate has no input events and no dirty rects.
onCtrlEsc ctrlEscHandler Invokes shellCtrlEscFn if the Task Manager DXE is loaded.
onF1 f1HelpHandler Launches the help viewer, optionally passing the focused app's helpFile and helpTopic.
onTitleChange titleChangeHandler Runs shellDesktopUpdate so Program Manager window lists refresh.</pre>
<h2>shellRegisterDesktopUpdate</h2>
<pre><code>void shellRegisterDesktopUpdate(void (*updateFn)(void));</code></pre>
<p>Register a callback for app state change notifications. Multiple callbacks are supported. Apps typically call this during appMain() to receive notifications.</p>
<h2>shellUnregisterDesktopUpdate</h2>
<pre><code>void shellUnregisterDesktopUpdate(void (*updateFn)(void));</code></pre>
<p>Remove a previously registered callback. Call this before app shutdown to avoid dangling function pointers.</p>
<h2>shellDesktopUpdate</h2>
<pre><code>void shellDesktopUpdate(void);</code></pre>
<p>Notify all registered desktop callbacks that app state has changed. Called internally by the shell after loading or reaping an app. Can also be called by apps that need to trigger a desktop refresh.</p>
<h2>shellCtrlEscFn</h2>
<pre><code>extern void (*shellCtrlEscFn)(AppContextT *ctx);</code></pre>
<p>Function pointer set by the taskmgr DXE's constructor. The shell calls this when Ctrl+Esc is pressed. NULL if the task manager is not loaded.</p>
</div>
<div class="topic" id="shell.info">
<h1>System Information</h1>
<p>Header: dvxshell/shellInf.h</p>
<p>Thin wrapper around the platform layer's hardware detection. Gathers system information at startup, logs it, and caches the result for display in dialogs.</p>
<h2>shellInfoInit</h2>
<pre><code>void shellInfoInit(AppContextT *ctx);</code></pre>
<p>Gather all hardware information via the platform layer, log each line to DVX.LOG, and store the result for later retrieval. Call once after dvxInit().</p>
<h2>shellGetSystemInfo</h2>
<pre><code>const char *shellGetSystemInfo(void);</code></pre>
<p>Return the formatted system information text. The returned pointer is valid for the lifetime of the process (static buffer in the platform layer).</p>
</div>
<div class="topic" id="sql.overview">
<h2>dvxSql -- SQL Database Interface</h2>
<p>High-level wrapper around SQLite3 for DVX applications. Manages database connections and result set cursors via integer handles so BASIC code never touches raw pointers. All handles are 1-based; 0 indicates an error or invalid handle.</p>
<p>Header: sql/dvxSql.h</p>
<h3>SQLite Wrapping</h3>
<p>dvxSql wraps the bundled SQLite3 amalgamation (sql/thirdparty/sqlite/examples/sqlite3.h). It manages two internal dynamic tables keyed by 1-based handles:</p>
<ul>
<li>Database table: each slot holds a sqlite3 * plus a per-database error string and affected-row count.</li>
</ul>
<p>Cursor table: each slot holds a sqlite3_stmt *, the owning database handle, and EOF tracking.</p>
<p>Growing either table doubles its capacity. Closed slots are recycled by subsequent dvxSqlOpen or dvxSqlQuery calls, keeping handle values stable for the caller.</p>
<h3>Handle Model</h3>
<p>Database and cursor handles are int32_t values. A successful open or query returns a handle greater than zero. Handle 0 is reserved as the invalid/error sentinel. Closing a database automatically finalizes all cursors that belong to it, so callers do not need to track cursor lifetimes per-database.</p>
<h3>Connection Lifecycle</h3>
<ul>
<li>dvxSqlOpen allocates a handle and calls sqlite3_open. The database file is created if it does not exist.</li>
<li>Use dvxSqlExec for DDL and non-query DML. On success, dvxSqlAffectedRows returns the row count for the last call on this handle.</li>
<li>Use dvxSqlQuery to obtain a cursor over a SELECT. Iterate with dvxSqlNext and read columns with dvxSqlFieldText, dvxSqlFieldInt, dvxSqlFieldDbl, or dvxSqlFieldByName.</li>
</ul>
<p>Call dvxSqlFreeResult when the cursor is no longer needed. Call dvxSqlClose when the database is no longer needed; any cursors still open on that database are finalized automatically.</p>
<h3>Common Patterns</h3>
<ul>
<li>Parameterize user input with dvxSqlEscape before interpolating into SQL strings.</li>
<li>Check dvxSqlError(db) for the last error on a handle; its message is stable until the next operation on the same database.</li>
</ul>
<p>dvxSqlFieldByName matches column names case-insensitively, suitable for most real-world schemas.</p>
<p><a href="#sql.db">Database Operations</a></p>
<p><a href="#sql.cursor">Cursor Operations</a></p>
<p><a href="#sql.utility">Utility Functions</a></p>
<p><a href="#sql.example">Example</a></p>
</div>
<div class="topic" id="sql.db">
<h2>Database Operations</h2>
<h3>dvxSqlOpen</h3>
<pre><code>int32_t dvxSqlOpen(const char *path);</code></pre>
<p>Open a SQLite database file. Creates the file if it does not exist.</p>
<pre> Parameter Description
--------- -----------
path Path to the database file.</pre>
<p>Returns a database handle greater than 0 on success, or 0 on error (null path, open failure, or no free slots).</p>
<h3>dvxSqlClose</h3>
<pre><code>void dvxSqlClose(int32_t db);</code></pre>
<p>Close a database and free all associated resources. Any open cursors belonging to this database are automatically finalized.</p>
<pre> Parameter Description
--------- -----------
db Database handle returned by dvxSqlOpen.</pre>
<p>Safe to call with an invalid handle (no-op).</p>
<h3>dvxSqlExec</h3>
<pre><code>bool dvxSqlExec(int32_t db, const char *sql);</code></pre>
<p>Execute one or more SQL statements that return no result rows. Suitable for DDL (CREATE TABLE, DROP TABLE, etc.) and DML (INSERT, UPDATE, DELETE).</p>
<pre> Parameter Description
--------- -----------
db Database handle.
sql SQL statement(s) to execute.</pre>
<p>Returns true on success, false on error. On failure, the error message is available via dvxSqlError. On success, the affected row count is available via dvxSqlAffectedRows.</p>
<h3>dvxSqlError</h3>
<pre><code>const char *dvxSqlError(int32_t db);</code></pre>
<p>Return the last error message for a database handle. The returned string is stored internally and valid until the next operation on the same handle.</p>
<pre> Parameter Description
--------- -----------
db Database handle.</pre>
<p>Returns the error string, or &quot;Invalid database handle&quot; if the handle is invalid.</p>
<h3>dvxSqlAffectedRows</h3>
<pre><code>int32_t dvxSqlAffectedRows(int32_t db);</code></pre>
<p>Return the number of rows inserted, updated, or deleted by the last dvxSqlExec call on this handle.</p>
<pre> Parameter Description
--------- -----------
db Database handle.</pre>
<p>Returns the row count, or 0 if the handle is invalid.</p>
</div>
<div class="topic" id="sql.cursor">
<h2>Cursor Operations</h2>
<p>Result set cursors are created by dvxSqlQuery and must be freed with dvxSqlFreeResult when no longer needed. A new cursor is positioned before the first row; call dvxSqlNext to advance to the first row before reading field values.</p>
<h3>dvxSqlQuery</h3>
<pre><code>int32_t dvxSqlQuery(int32_t db, const char *sql);</code></pre>
<p>Execute a SELECT query and return a cursor handle for iterating the results. The cursor is positioned before the first row.</p>
<pre> Parameter Description
--------- -----------
db Database handle.
sql SQL SELECT statement.</pre>
<p>Returns a cursor handle greater than 0 on success, or 0 on error (invalid handle, null SQL, SQL syntax error, or no free cursor slots). On failure, the error message is available via dvxSqlError on the database handle.</p>
<h3>dvxSqlNext</h3>
<pre><code>bool dvxSqlNext(int32_t rs);</code></pre>
<p>Advance the cursor to the next row.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle returned by dvxSqlQuery.</pre>
<p>Returns true if a row is now available for reading, false if the cursor has reached the end or the handle is invalid.</p>
<h3>dvxSqlEof</h3>
<pre><code>bool dvxSqlEof(int32_t rs);</code></pre>
<p>Test whether the cursor is past the last row.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle.</pre>
<p>Returns true if the cursor is exhausted or the handle is invalid, false otherwise.</p>
<h3>dvxSqlFieldCount</h3>
<pre><code>int32_t dvxSqlFieldCount(int32_t rs);</code></pre>
<p>Return the number of columns in the result set.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle.</pre>
<p>Returns the column count, or 0 if the handle is invalid.</p>
<h3>dvxSqlFieldName</h3>
<pre><code>const char *dvxSqlFieldName(int32_t rs, int32_t col);</code></pre>
<p>Return the name of a column by index.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle.
col Column index (0-based).</pre>
<p>Returns the column name, or &quot;&quot; if the handle or index is invalid.</p>
<h3>dvxSqlFieldText</h3>
<pre><code>const char *dvxSqlFieldText(int32_t rs, int32_t col);</code></pre>
<p>Return the value of a column as a string.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle.
col Column index (0-based).</pre>
<p>Returns the text value, or &quot;&quot; if the handle or index is invalid or the value is NULL.</p>
<h3>dvxSqlFieldByName</h3>
<pre><code>const char *dvxSqlFieldByName(int32_t rs, const char *name);</code></pre>
<p>Return the value of a column identified by name as a string. The name match is case-insensitive.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle.
name Column name (case-insensitive).</pre>
<p>Returns the text value, or &quot;&quot; if the handle is invalid, the name is NULL, or no column with that name exists.</p>
<h3>dvxSqlFieldInt</h3>
<pre><code>int32_t dvxSqlFieldInt(int32_t rs, int32_t col);</code></pre>
<p>Return the value of a column as a 32-bit integer.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle.
col Column index (0-based).</pre>
<p>Returns the integer value, or 0 if the handle or index is invalid.</p>
<h3>dvxSqlFieldDbl</h3>
<pre><code>double dvxSqlFieldDbl(int32_t rs, int32_t col);</code></pre>
<p>Return the value of a column as a double-precision floating point number.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle.
col Column index (0-based).</pre>
<p>Returns the double value, or 0.0 if the handle or index is invalid.</p>
<h3>dvxSqlFreeResult</h3>
<pre><code>void dvxSqlFreeResult(int32_t rs);</code></pre>
<p>Close a result set cursor and free its resources. Must be called for every cursor returned by dvxSqlQuery.</p>
<pre> Parameter Description
--------- -----------
rs Cursor handle.</pre>
<p>Safe to call with an invalid handle (no-op).</p>
</div>
<div class="topic" id="sql.utility">
<h2>Utility Functions</h2>
<h3>dvxSqlEscape</h3>
<pre><code>int32_t dvxSqlEscape(const char *src, char *dst, int32_t dstSize);</code></pre>
<p>Escape a string for safe inclusion in SQL string literals. Doubles single quotes so that O'Brien becomes O''Brien.</p>
<pre> Parameter Description
--------- -----------
src Source string to escape.
dst Destination buffer for the escaped string.
dstSize Size of the destination buffer in bytes.</pre>
<p>Returns the length of the escaped string (not including the null terminator), or -1 if the buffer was too small or any parameter is NULL/invalid.</p>
</div>
<div class="topic" id="sql.example">
<h2>Example Usage</h2>
<h3>Creating a Table and Inserting Data</h3>
<pre><code>int32_t db = dvxSqlOpen(&quot;mydata.db&quot;);
if (!db) {
// handle error
}
dvxSqlExec(db, &quot;CREATE TABLE IF NOT EXISTS contacts (&quot;
&quot;id INTEGER PRIMARY KEY, &quot;
&quot;name TEXT, &quot;
&quot;phone TEXT)&quot;);
dvxSqlExec(db, &quot;INSERT INTO contacts (name, phone) &quot;
&quot;VALUES ('Alice', '555-0100')&quot;);</code></pre>
<h3>Querying and Iterating Results</h3>
<pre><code>int32_t rs = dvxSqlQuery(db, &quot;SELECT id, name, phone FROM contacts&quot;);
if (!rs) {
printf(&quot;Error: %s\n&quot;, dvxSqlError(db));
}
while (dvxSqlNext(rs)) {
int32_t id = dvxSqlFieldInt(rs, 0);
const char *name = dvxSqlFieldText(rs, 1);
const char *phone = dvxSqlFieldText(rs, 2);
printf(&quot;%d: %s -- %s\n&quot;, id, name, phone);
}
dvxSqlFreeResult(rs);
dvxSqlClose(db);</code></pre>
<h3>Escaping User Input</h3>
<pre><code>char escaped[512];
dvxSqlEscape(userInput, escaped, sizeof(escaped));
char sql[1024];
snprintf(sql, sizeof(sql),
&quot;INSERT INTO notes (text) VALUES ('%s')&quot;, escaped);
dvxSqlExec(db, sql);</code></pre>
</div>
<div class="topic" id="lib.texthelp">
<h1>Text Help Library</h1>
<p>Shared text editing infrastructure library for DVX widget DXEs. Provides cursor blink management, cross-widget selection clearing, word boundary logic, and a complete single-line text editing engine. Used by TextInput, Spinner, ComboBox, AnsiTerm, and other widgets that need text editing behavior.</p>
<p>Header: texthelp/textHelp.h</p>
<p>Loaded as: bin/libs/texthelp.lib</p>
<h2>How Widgets Use This Library</h2>
<p>Widget DXEs that implement text editing delegate to textHelp for the four high-cost behaviors:</p>
<ul>
<li>Cursor blink. The library tracks a 250 ms blink timer in a static global and the focused widget reads sCursorBlinkOn (exposed via libdvx) when repainting.</li>
<li>Selection clearing. When a widget gains focus it calls clearOtherSelections(self) so only one widget ever has an active text selection.</li>
<li>Word boundaries. isWordChar, wordStart/wordEnd, and wordBoundaryLeft/wordBoundaryRight implement the logic for double-click word selection and Ctrl+Left/Right navigation in a uniform way.</li>
</ul>
<p>Single-line editing engine. widgetTextEditOnKey, widgetTextEditMouseClick, widgetTextEditDragUpdateLine, and widgetTextEditPaintLine form a pointer-parameterized implementation of keyboard, mouse, drag, and paint behaviors. Widgets (TextInput, Spinner, ComboBox, AnsiTerm) hand the library pointers to their internal buffer, cursor, scroll offset, and selection state.</p>
<p>The engine is intentionally pointer-parameterized rather than struct-based so widgets can reuse it without adopting a shared state struct. Each widget owns its own buffer and state and passes pointers in on every call.</p>
<h2>Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
TEXT_INPUT_PAD 3 Pixel padding inside text editing fields.</pre>
</div>
<div class="topic" id="lib.texthelp.cursorblink">
<h2>wgtUpdateCursorBlink</h2>
<p>Advances the cursor blink timer. When the blink interval (250 ms) elapses, toggles the global sCursorBlinkOn flag and invalidates the currently focused widget for repaint. Registered automatically at library load time via a constructor function that sets the sCursorBlinkFn pointer.</p>
<pre><code>void wgtUpdateCursorBlink(void);</code></pre>
<p>Takes no arguments and returns nothing. Called by the core event loop.</p>
</div>
<div class="topic" id="lib.texthelp.clearother">
<h2>clearOtherSelections</h2>
<p>Clears the text selection on whichever widget previously had one, unless that widget is the one passed as the argument. Tracks the last selected widget in a static pointer for O(1) lookup instead of walking the widget tree. Validates that the previous widget's window is still in the window stack before touching it, so stale pointers from closed windows are handled safely. If the previous selection was in a different window, that window gets a full repaint to clear the stale highlight.</p>
<pre><code>void clearOtherSelections(WidgetT *except);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
except WidgetT * The widget that now owns the selection. Its selection is preserved.</pre>
</div>
<div class="topic" id="lib.texthelp.iswordchar">
<h2>isWordChar</h2>
<p>Returns true if the character is alphanumeric or underscore. Used by word boundary functions to define what constitutes a &quot;word&quot; for double-click selection and Ctrl+arrow navigation.</p>
<pre><code>bool isWordChar(char c);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
c char The character to test.</pre>
<p>Returns true if c is alphanumeric (a-z, A-Z, 0-9) or underscore.</p>
</div>
<div class="topic" id="lib.texthelp.wordend">
<h2>wordEnd</h2>
<p>Scans forward from the given position, returning the index of the first non-word character. Used to find the right boundary of a word for double-click word selection.</p>
<pre><code>int32_t wordEnd(const char *buf, int32_t len, int32_t pos);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
buf const char * The text buffer to scan.
len int32_t Length of the text in the buffer.
pos int32_t Starting position (character index).</pre>
<p>Returns the index one past the last word character.</p>
</div>
<div class="topic" id="lib.texthelp.wordstart">
<h2>wordStart</h2>
<p>Scans backward from the given position, returning the index of the first character of the current word. Used to find the left boundary of a word for double-click word selection.</p>
<pre><code>int32_t wordStart(const char *buf, int32_t pos);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
buf const char * The text buffer to scan.
pos int32_t Starting position (character index).</pre>
<p>Returns the index of the first character of the word containing pos.</p>
</div>
<div class="topic" id="lib.texthelp.wordboundaryleft">
<h2>wordBoundaryLeft</h2>
<p>Finds the left word boundary for Ctrl+Left navigation. Skips non-word characters first, then skips word characters, leaving the cursor at the start of the previous word.</p>
<pre><code>int32_t wordBoundaryLeft(const char *buf, int32_t pos);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
buf const char * The text buffer to scan.
pos int32_t Starting position (character index).</pre>
<p>Returns the index of the previous word boundary. Returns 0 if pos is already at or before the start of the buffer.</p>
</div>
<div class="topic" id="lib.texthelp.wordboundaryright">
<h2>wordBoundaryRight</h2>
<p>Finds the right word boundary for Ctrl+Right navigation. Skips word characters first, then skips non-word characters, leaving the cursor at the start of the next word.</p>
<pre><code>int32_t wordBoundaryRight(const char *buf, int32_t len, int32_t pos);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
buf const char * The text buffer to scan.
len int32_t Length of the text buffer.
pos int32_t Starting position (character index).</pre>
<p>Returns the index of the next word boundary. Returns len if pos is already at or past the end of the buffer.</p>
</div>
<div class="topic" id="lib.texthelp.saveundo">
<h2>textEditSaveUndo</h2>
<p>Capture a snapshot of the current buffer contents and cursor position into an undo buffer. Called by widgetTextEditOnKey before every destructive operation (insert, delete, paste, cut). Truncates to bufSize - 1 characters so the null terminator always fits.</p>
<pre><code>void textEditSaveUndo(char *buf, int32_t len,
int32_t cursor, char *undoBuf,
int32_t *pUndoLen, int32_t *pUndoCursor,
int32_t bufSize);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
buf char * Source buffer to snapshot.
len int32_t Current length of source contents.
cursor int32_t Current cursor position to save.
undoBuf char * Destination undo buffer. If NULL the call is a no-op.
pUndoLen int32_t * [out] Length of saved undo contents.
pUndoCursor int32_t * [out] Saved cursor position.
bufSize int32_t Size of the destination undo buffer including the null terminator.</pre>
</div>
<div class="topic" id="lib.texthelp.dragupdate">
<h2>widgetTextEditDragUpdateLine</h2>
<p>Called during mouse drag to extend the selection in a single-line text field. Converts a viewport-relative pixel x coordinate to a character position and updates the cursor and selection end accordingly. Auto-scrolls the text when the mouse moves past the left or right visible edge.</p>
<pre><code>void widgetTextEditDragUpdateLine(
int32_t vx, int32_t leftEdge, int32_t maxChars,
const BitmapFontT *font, int32_t len,
int32_t *pCursorPos, int32_t *pScrollOff,
int32_t *pSelEnd);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
vx int32_t Mouse x position in viewport coordinates.
leftEdge int32_t Pixel x of the left edge of the text area.
maxChars int32_t Maximum visible characters in the field.
font const BitmapFontT * Bitmap font used for character width.
len int32_t Total length of the text buffer.
pCursorPos int32_t * [in/out] Current cursor position.
pScrollOff int32_t * [in/out] Horizontal scroll offset in characters.
pSelEnd int32_t * [out] Updated selection end position.</pre>
</div>
<div class="topic" id="lib.texthelp.mouseclick">
<h2>widgetTextEditMouseClick</h2>
<p>Handles mouse click events for single-line text widgets. Converts pixel coordinates to a character position using the font's character width. Detects multi-click sequences via the core multiClickDetect() function:</p>
<ul>
<li>Single click -- places the cursor and begins a potential drag selection.</li>
<li>Double click -- selects the word under the cursor (if wordSelect is true), or selects all text.</li>
</ul>
<p>Triple click -- selects all text in the field.</p>
<pre><code>void widgetTextEditMouseClick(
WidgetT *w, int32_t vx, int32_t vy,
int32_t textLeftX, const BitmapFontT *font,
const char *buf, int32_t len, int32_t scrollOff,
int32_t *pCursorPos, int32_t *pSelStart,
int32_t *pSelEnd, bool wordSelect,
bool dragSelect);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
w WidgetT * The widget receiving the click.
vx int32_t Mouse x in viewport coordinates.
vy int32_t Mouse y in viewport coordinates.
textLeftX int32_t Pixel x of the left edge of the text area.
font const BitmapFontT * Bitmap font for character width calculation.
buf const char * Text buffer contents.
len int32_t Length of text in the buffer.
scrollOff int32_t Current horizontal scroll offset.
pCursorPos int32_t * [out] Computed cursor position.
pSelStart int32_t * [out] Selection start.
pSelEnd int32_t * [out] Selection end.
wordSelect bool If true, double-click selects word; if false, selects all.
dragSelect bool If true, single-click begins drag selection.</pre>
</div>
<div class="topic" id="lib.texthelp.onkey">
<h2>widgetTextEditOnKey</h2>
<p>The core single-line text editing engine. Processes a single keystroke and updates the buffer, cursor, scroll offset, selection, and undo state. All state is passed by pointer so the function is reusable across TextInput, Spinner, ComboBox, and any other single-line widget.</p>
<pre><code>void widgetTextEditOnKey(
WidgetT *w, int32_t key, int32_t mod,
char *buf, int32_t bufSize,
int32_t *pLen, int32_t *pCursor,
int32_t *pScrollOff,
int32_t *pSelStart, int32_t *pSelEnd,
char *undoBuf, int32_t *pUndoLen,
int32_t *pUndoCursor, int32_t fieldWidth);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
w WidgetT * The widget receiving the key event.
key int32_t Key code (ASCII for printable, control code or scan|0x100 for extended).
mod int32_t Modifier flags (KEY_MOD_SHIFT, etc.).
buf char * [in/out] The text buffer.
bufSize int32_t Total size of the buffer including null terminator.
pLen int32_t * [in/out] Current text length.
pCursor int32_t * [in/out] Cursor position (character index).
pScrollOff int32_t * [in/out] Horizontal scroll offset.
pSelStart int32_t * [in/out] Selection start (-1 if no selection).
pSelEnd int32_t * [in/out] Selection end (-1 if no selection).
undoBuf char * Undo buffer (same size as buf). NULL to disable undo.
pUndoLen int32_t * [in/out] Length of undo buffer contents.
pUndoCursor int32_t * [in/out] Cursor position saved in undo state.
fieldWidth int32_t Visible field width in pixels. 0 = use widget width.</pre>
<h3>Supported Keys</h3>
<pre> Key Action
--- ------
Printable Insert character at cursor (replaces selection if active).
Backspace Delete character before cursor or delete selection.
Delete Delete character after cursor or delete selection.
Left Move cursor left. With Shift, extend selection.
Right Move cursor right. With Shift, extend selection.
Ctrl+Left Move cursor to previous word boundary. With Shift, extend selection.
Ctrl+Right Move cursor to next word boundary. With Shift, extend selection.
Home Move cursor to start. With Shift, extend selection.
End Move cursor to end. With Shift, extend selection.
Ctrl+A Select all text.
Ctrl+C Copy selection to clipboard.
Ctrl+V Paste from clipboard (newlines stripped).
Ctrl+X Cut selection to clipboard.
Ctrl+Z Undo (swaps current and undo buffers).</pre>
<p>Fires w-&gt;onChange after any mutation (insert, delete, paste, cut, undo). Automatically adjusts scroll offset to keep cursor visible after every operation.</p>
</div>
<div class="topic" id="lib.texthelp.paintline">
<h2>widgetTextEditPaintLine</h2>
<p>Renders a single line of text with optional selection highlighting and a blinking cursor. Splits the visible text into up to three segments (pre-selection, selection, post-selection) and draws each with appropriate colors. The selection highlight uses the menu highlight colors from the color scheme. The cursor is drawn as a one-pixel vertical line when sCursorBlinkOn is true.</p>
<pre><code>void widgetTextEditPaintLine(
DisplayT *d, const BlitOpsT *ops,
const BitmapFontT *font,
const ColorSchemeT *colors,
int32_t textX, int32_t textY,
const char *buf, int32_t visLen,
int32_t scrollOff, int32_t cursorPos,
int32_t selStart, int32_t selEnd,
uint32_t fg, uint32_t bg,
bool showCursor,
int32_t cursorMinX, int32_t cursorMaxX);</code></pre>
<pre> Parameter Type Description
--------- ---- -----------
d DisplayT * Display context for drawing.
ops const BlitOpsT * Blit operations table for the current pixel format.
font const BitmapFontT * Bitmap font for text rendering.
colors const ColorSchemeT * Color scheme (used for selection highlight colors).
textX int32_t Pixel x of the start of visible text.
textY int32_t Pixel y of the text baseline.
buf const char * Visible portion of the text buffer (buf + scrollOff).
visLen int32_t Number of visible characters to draw.
scrollOff int32_t Scroll offset (used to map selection to visible range).
cursorPos int32_t Absolute cursor position in the full buffer.
selStart int32_t Selection start (-1 if no selection).
selEnd int32_t Selection end (-1 if no selection).
fg uint32_t Foreground (text) color.
bg uint32_t Background color.
showCursor bool Whether to draw the cursor (false when widget lacks focus).
cursorMinX int32_t Left clipping bound for cursor drawing.
cursorMaxX int32_t Right clipping bound for cursor drawing.</pre>
</div>
<div class="topic" id="lib.listhelp">
<h1>List Helper Library</h1>
<p>Shared helper routines for dropdown and list-based widget DXEs (ListBox, Dropdown, ComboBox, ListView). Provides dropdown arrow rendering, item measurement, keyboard navigation, popup geometry calculation, popup list painting, type-ahead search, and popup scrollbar hit testing.</p>
<p>Header: listhelp/listHelp.h</p>
<p>Loaded as: bin/libs/listhelp.lib</p>
<h2>Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
DROPDOWN_BTN_WIDTH 16 Width of the dropdown arrow button in pixels.
DROPDOWN_MAX_VISIBLE 8 Maximum number of items visible in a popup list before scrolling.
POPUP_SCROLLBAR_W SCROLLBAR_WIDTH Popup vertical scrollbar width (mirrors the core window-manager scrollbar width).</pre>
<h2>widgetDrawDropdownArrow</h2>
<p>Draw the triangular dropdown arrow glyph centered at a given position.</p>
<pre><code>void widgetDrawDropdownArrow(DisplayT *d, const BlitOpsT *ops,
int32_t centerX, int32_t centerY, uint32_t color);</code></pre>
<pre> Parameter Description
--------- -----------
d Display context.
ops Blit operations vtable for the active pixel depth.
centerX Horizontal center of the arrow in backbuffer coordinates.
centerY Vertical center of the arrow in backbuffer coordinates.
color Pre-packed pixel color for the arrow.</pre>
<h2>widgetMaxItemLen</h2>
<p>Scan an array of strings and return the length (in characters) of the longest item.</p>
<pre><code>int32_t widgetMaxItemLen(const char **items, int32_t count);</code></pre>
<pre> Parameter Description
--------- -----------
items Array of null-terminated string pointers.
count Number of items in the array.</pre>
<p>Returns the character length of the longest item, or 0 if count is zero.</p>
<h2>widgetNavigateIndex</h2>
<p>Compute a new selected index from a navigation key press. Handles Up, Down, Home, End, Page Up, and Page Down.</p>
<pre><code>int32_t widgetNavigateIndex(int32_t key, int32_t current,
int32_t count, int32_t pageSize);</code></pre>
<pre> Parameter Description
--------- -----------
key Keyboard scancode (Up, Down, Home, End, PgUp, PgDn).
current Currently selected index.
count Total number of items in the list.
pageSize Number of visible items (used for PgUp/PgDn step size).</pre>
<p>Returns the new index, clamped to [0, count-1]. Returns -1 for unrecognized keys so callers can detect whether the key was consumed.</p>
<h2>widgetDropdownPopupRect</h2>
<p>Calculate the screen rectangle for a dropdown popup list, positioning it below the owning widget and clamping to screen bounds.</p>
<pre><code>void widgetDropdownPopupRect(WidgetT *w, const BitmapFontT *font,
int32_t contentH, int32_t itemCount,
int32_t *popX, int32_t *popY, int32_t *popW, int32_t *popH);</code></pre>
<pre> Parameter Description
--------- -----------
w The widget that owns the popup (Dropdown, ComboBox, etc.).
font Bitmap font used for item text (determines row height).
contentH Height of the widget's content area in pixels.
itemCount Total number of items in the list.
popX Output: popup X position (screen coordinates).
popY Output: popup Y position (screen coordinates).
popW Output: popup width in pixels.
popH Output: popup height in pixels.</pre>
<p>The popup is sized to show up to DROPDOWN_MAX_VISIBLE items.</p>
<h2>widgetPaintPopupList</h2>
<p>Render a popup item list with highlight, scrolling, and beveled border. When itemCount exceeds DROPDOWN_MAX_VISIBLE, draws a vertical scrollbar on the right edge sized according to scrollPos.</p>
<pre><code>void widgetPaintPopupList(DisplayT *d, const BlitOpsT *ops,
const BitmapFontT *font, const ColorSchemeT *colors,
int32_t popX, int32_t popY, int32_t popW, int32_t popH,
const char **items, int32_t itemCount,
int32_t hoverIdx, int32_t scrollPos);</code></pre>
<pre> Parameter Description
--------- -----------
d Display context.
ops Blit operations vtable.
font Bitmap font for rendering item text.
colors Color scheme for background, text, and highlight colors.
popX Popup X position (from widgetDropdownPopupRect).
popY Popup Y position.
popW Popup width.
popH Popup height.
items Array of null-terminated item strings.
itemCount Total number of items.
hoverIdx Index of the highlighted (hovered/selected) item, or -1 for none.
scrollPos Index of the first visible item (scroll offset).</pre>
<h2>widgetTypeAheadSearch</h2>
<p>Case-insensitive type-ahead search. Scans items forward from currentIdx + 1, wrapping around, for the next item whose first character matches ch. Used by list and dropdown widgets to jump to an item based on a single keystroke.</p>
<pre><code>int32_t widgetTypeAheadSearch(char ch, const char **items,
int32_t itemCount, int32_t currentIdx);</code></pre>
<pre> Parameter Description
--------- -----------
ch Character to match (case-insensitive).
items Array of null-terminated item strings.
itemCount Number of items in the array.
currentIdx Currently selected index (search starts at currentIdx + 1 and wraps).</pre>
<p>Returns the index of the next matching item, or -1 if no match is found or itemCount is not positive.</p>
<h2>widgetPopupScrollbarClick</h2>
<p>Hit-test a popup scrollbar click. Tests whether the (x, y) coordinate falls on the popup's vertical scrollbar track; if so, updates scrollPos for up/down arrow clicks or page-up/page-down clicks in the trough. No-op on the thumb itself (callers handle drag separately).</p>
<pre><code>bool widgetPopupScrollbarClick(int32_t x, int32_t y,
int32_t popX, int32_t popY, int32_t popW, int32_t popH,
int32_t itemCount, int32_t visibleItems,
int32_t *scrollPos);</code></pre>
<pre> Parameter Description
--------- -----------
x Click X in the popup's coordinate space.
y Click Y in the popup's coordinate space.
popX Popup X origin.
popY Popup Y origin.
popW Popup width.
popH Popup height.
itemCount Total number of items.
visibleItems Number of visible rows in the popup.
scrollPos [in/out] Current scroll offset; updated in place when the click hits the scrollbar.</pre>
<p>Returns true if the click landed on the scrollbar (even if scrollPos was not changed, for example clicking the thumb), false if the click was in the item list area. When itemCount is less than or equal to DROPDOWN_MAX_VISIBLE, always returns false (there is no scrollbar).</p>
</div>
<div class="topic" id="lib.taskmgr">
<h1>Task Manager</h1>
<p>System-level task manager for DVX. Displays all running applications with a six-column ListView (Name, Title, File, Type, Memory, Status) and exposes Switch To, End Task, and Run... operations. Always accessible via Ctrl+Esc regardless of which application is focused. Persists independently of the desktop app (Program Manager).</p>
<p>Header: taskmgr/shellTaskMgr.h</p>
<p>Loaded as: bin/libs/taskmgr.lib</p>
<h2>Integration</h2>
<p>The task manager is a shell-level library, not a regular DXE app. At DXE load time a GCC constructor function registers the Task Manager with the shell by setting the shellCtrlEscFn function pointer (declared extern in dvxshell/shellApp.h). The shell invokes shellCtrlEscFn on every Ctrl+Esc keystroke; if taskmgr.lib is not loaded the pointer stays NULL and Ctrl+Esc does nothing.</p>
<p>The Task Manager owns its window on behalf of the shell itself (appId = 0), not any running app, which is why it survives when the desktop app terminates. It registers shellTaskMgrRefresh with shellRegisterDesktopUpdate so the list refreshes live as apps load, reap, or crash.</p>
<h2>Integration with libtasks</h2>
<p>The Task Manager reads from the shell's app slot table (shellGetApp, shellAppSlotCount, shellRunningAppCount) rather than from the libtasks scheduler directly. Each ShellAppT slot carries its cooperative task ID when hasMainLoop is true; End Task calls shellForceKillApp, which in turn calls tsKill on that task ID (for main-loop apps) after destroying the app's windows.</p>
<h2>Features</h2>
<ul>
<li>Six-column ListView showing Name, Title, File, Type (Task or Callback), Memory (from dvxMemGetAppUsage), and Status for every running app.</li>
<li>Switch To button (Alt+S): raises and focuses the selected app's topmost window, restoring it if minimized. Also triggered by double-clicking a row.</li>
<li>End Task button (Alt+E): force-kills the selected app via shellForceKillApp.</li>
<li>Run... button (Alt+R): opens a file dialog to browse for and launch a .app file.</li>
<li>Status bar showing running app count plus total and used system memory.</li>
</ul>
<p>Single-instance: reopening the Task Manager while it is already visible raises and focuses the existing window rather than creating a new one.</p>
<h2>shellTaskMgrOpen</h2>
<p>Open the Task Manager window, or raise it to the front if already open.</p>
<pre><code>void shellTaskMgrOpen(AppContextT *ctx);</code></pre>
<pre> Parameter Description
--------- -----------
ctx Application context (from dvxInit). Required for window creation, stack manipulation, and registering the desktop-update callback.</pre>
<p>Called by the shell's global Ctrl+Esc handler via the shellCtrlEscFn hook.</p>
<h2>shellTaskMgrRefresh</h2>
<p>Rebuild the task list display from the current shell app slot table and refresh the status bar. Registered with shellRegisterDesktopUpdate at open time so it is invoked whenever the shell detects app state changes.</p>
<pre><code>void shellTaskMgrRefresh(void);</code></pre>
<p>Takes no parameters. Safe to call even if the Task Manager window is not currently open (the call is a no-op in that case).</p>
</div>
<div class="topic" id="lib.serial">
<h1>Serial Stack</h1>
<p>The DVX serial/networking stack provides reliable, optionally encrypted communication over RS-232 serial ports. It is composed of four layers, each building on the one below:</p>
<ul>
<li>rs232 -- ISR-driven UART driver with ring buffers and flow control</li>
<li>packet -- HDLC framing, CRC-16, Go-Back-N ARQ (reliable delivery)</li>
<li>security -- 1024-bit Diffie-Hellman key exchange, XTEA-CTR cipher, DRBG RNG</li>
</ul>
<p>secLink -- Convenience wrapper: channel multiplexing, per-packet encryption</p>
<p>Loaded as: bin/libs/kpunch/serial/serial.lib</p>
<h2>Layered Architecture</h2>
<pre><code>+--------------------------------------------------+
| Application |
| |
| secLinkSend() -- send on channel, opt. encrypt |
| secLinkPoll() -- receive + dispatch |
+--------------------------------------------------+
| secLink (channel multiplex, TX/RX ciphers) |
+--------------------------------------------------+
| packet (HDLC framing, CRC-16, Go-Back-N ARQ) |
+--------------------------------------------------+
| security -- DH key exchange, XTEA-CTR, DRBG |
| (used by secLink during handshake) |
+--------------------------------------------------+
| rs232 (ISR-driven UART, 2048-byte rings) |
+--------------------------------------------------+
| UART hardware (8250 / 16450 / 16550 / 16550A) |
+--------------------------------------------------+</code></pre>
<p>The security layer is invoked by secLink during the Diffie-Hellman handshake and for per-packet cipher operations. It has no runtime coupling to rs232 or packet, so it can be used standalone for cryptographic operations independent of the serial stack.</p>
<p><a href="#lib.serial.rs232">Layer 1: RS-232 UART Driver</a></p>
<p><a href="#lib.serial.packet">Layer 2: Packet Transport</a></p>
<p><a href="#lib.serial.security">Layer 3: Security (DH + XTEA)</a></p>
<p><a href="#lib.serial.seclink">Layer 4: Secure Link</a></p>
<p><a href="#lib.serial.example">End-to-End Example</a></p>
</div>
<div class="topic" id="lib.serial.rs232">
<h1>RS-232 UART Driver</h1>
<p>ISR-driven serial port driver supporting up to 4 simultaneous COM ports. A shared ISR drains UART FIFOs into per-port ring buffers (2048 bytes, power-of-2 for fast index wrapping). Flow control (XON/XOFF, RTS/CTS, DTR/DSR) operates within the ISR using watermark thresholds. All ISR data structures are DPMI-locked to prevent page faults.</p>
<p>Header: rs232/rs232.h</p>
<h2>Port Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
RS232_COM1 0 First serial port.
RS232_COM2 1 Second serial port.
RS232_COM3 2 Third serial port.
RS232_COM4 3 Fourth serial port.
RS232_NUM_PORTS 4 Total number of supported COM ports.</pre>
<h2>Handshake Modes</h2>
<pre> Constant Value Description
-------- ----- -----------
RS232_HANDSHAKE_NONE 0 No flow control.
RS232_HANDSHAKE_XONXOFF 1 Software flow control (XON/XOFF characters).
RS232_HANDSHAKE_RTSCTS 2 Hardware flow control via RTS/CTS lines.
RS232_HANDSHAKE_DTRDSR 3 Hardware flow control via DTR/DSR lines.</pre>
<h2>UART Types</h2>
<p>Detected automatically by probing the scratch register and FIFO capability.</p>
<pre> Constant Value Description
-------- ----- -----------
RS232_UART_UNKNOWN 0 Detection failed.
RS232_UART_8250 1 Original IBM PC UART. No FIFO.
RS232_UART_16450 2 Has scratch register, no FIFO.
RS232_UART_16550 3 Has FIFO but buggy (rare).
RS232_UART_16550A 4 Working 16-byte FIFO. Most common in 486+ hardware.</pre>
<h2>Error Codes</h2>
<pre> Constant Value Description
-------- ----- -----------
RS232_SUCCESS 0 Operation succeeded.
RS232_ERR_UNKNOWN -1 Unknown error.
RS232_ERR_NOT_OPEN -2 Port is not open.
RS232_ERR_ALREADY_OPEN -3 Port is already open.
RS232_ERR_NO_UART -4 No UART detected at port address.
RS232_ERR_INVALID_PORT -5 Invalid port number.
RS232_ERR_INVALID_BASE -6 Invalid base I/O address.
RS232_ERR_INVALID_IRQ -7 Invalid IRQ number.
RS232_ERR_INVALID_BPS -8 Invalid baud rate.
RS232_ERR_INVALID_DATA -9 Invalid data bits value.
RS232_ERR_INVALID_PARITY -10 Invalid parity character.
RS232_ERR_INVALID_STOP -11 Invalid stop bits value.
RS232_ERR_INVALID_HANDSHAKE -12 Invalid handshake mode.
RS232_ERR_INVALID_FIFO -13 Invalid FIFO threshold.
RS232_ERR_NULL_PTR -14 NULL pointer argument.
RS232_ERR_IRQ_NOT_FOUND -15 Could not detect IRQ for port.
RS232_ERR_LOCK_MEM -16 DPMI memory lock failed.</pre>
<h2>rs232Open</h2>
<p>Open a COM port with the specified line parameters.</p>
<pre><code>int rs232Open(int com, int32_t bps, int dataBits,
char parity, int stopBits, int handshake);</code></pre>
<pre> Parameter Description
--------- -----------
com Port index (RS232_COM1..RS232_COM4).
bps Baud rate (e.g. 9600, 19200, 38400, 57600, 115200).
dataBits Data bits per character (5, 6, 7, or 8).
parity Parity mode: 'N' (none), 'O' (odd), 'E' (even), 'M' (mark), 'S' (space).
stopBits Stop bits (1 or 2).
handshake Flow control mode (RS232_HANDSHAKE_*).</pre>
<p>Returns RS232_SUCCESS or a negative error code.</p>
<h2>rs232Close</h2>
<p>Close a COM port and release its ISR resources.</p>
<pre><code>int rs232Close(int com);</code></pre>
<h2>rs232Read</h2>
<p>Non-blocking read from the receive ring buffer.</p>
<pre><code>int rs232Read(int com, char *data, int len);</code></pre>
<pre> Parameter Description
--------- -----------
com Port index.
data Buffer to receive data.
len Maximum bytes to read.</pre>
<p>Returns the number of bytes actually read (may be less than len).</p>
<h2>rs232Write</h2>
<p>Blocking polled write directly to UART transmit holding register. Bypasses the TX ring buffer. Polls LSR_TX_HOLD_EMPTY before writing each byte. Use for small, immediate writes where order matters (the packet layer uses this for frame transmission).</p>
<pre><code>int rs232Write(int com, const char *data, int len);</code></pre>
<p>Returns the number of bytes actually written (may be less than len if software flow control is asserted), or a negative error code (RS232_ERR_INVALID_PORT, RS232_ERR_NOT_OPEN, RS232_ERR_NULL_PTR).</p>
<h2>rs232WriteBuf</h2>
<p>Non-blocking write to the transmit ring buffer. The ISR drains buffered data to the UART asynchronously.</p>
<pre><code>int rs232WriteBuf(int com, const char *data, int len);</code></pre>
<p>Returns the number of bytes actually queued (may be less than len if the buffer is full).</p>
<h2>rs232Set</h2>
<p>Change all line parameters on an open port. Internally calls rs232SetBps, rs232SetData, rs232SetParity, rs232SetStop, and rs232SetHandshake in sequence. Returns RS232_SUCCESS on success or the first negative error code encountered.</p>
<pre><code>int rs232Set(int com, int32_t bps, int dataBits,
char parity, int stopBits, int handshake);</code></pre>
<h2>Configuration Getters</h2>
<pre> Function Returns
-------- -------
rs232GetBase(com) I/O base address.
rs232GetBps(com) Current baud rate (int32_t).
rs232GetData(com) Data bits setting (5-8).
rs232GetParity(com) Parity character: 'n', 'o', 'e', 'm', or 's' (lowercase).
rs232GetStop(com) Stop bits setting (1 or 2).
rs232GetHandshake(com) Handshake mode (RS232_HANDSHAKE_*).
rs232GetIrq(com) IRQ number.
rs232GetUartType(com) Detected UART type (RS232_UART_*).</pre>
<p>rs232GetParity returns a lowercase character on success. Callers comparing against uppercase constants must use either both cases or tolower().</p>
<h2>Status Getters</h2>
<pre> Function Returns
-------- -------
rs232GetRxBuffered(com) Bytes waiting in the receive ring buffer.
rs232GetTxBuffered(com) Bytes waiting in the transmit ring buffer.
rs232GetCts(com) CTS line state (0 or 1).
rs232GetDsr(com) DSR line state (0 or 1).
rs232GetDtr(com) DTR line state (0 or 1).
rs232GetRts(com) RTS line state (0 or 1).
rs232GetLsr(com) Line status register value.
rs232GetMcr(com) Modem control register value.
rs232GetMsr(com) Modem status register value.</pre>
<h2>Configuration Setters</h2>
<pre> Function Description
-------- -----------
rs232SetBase(com, base) Set I/O base address (before open).
rs232SetBps(com, bps) Change baud rate.
rs232SetData(com, dataBits) Change data bits.
rs232SetParity(com, parity) Change parity mode.
rs232SetStop(com, stopBits) Change stop bits.
rs232SetHandshake(com, handshake) Change flow control mode.
rs232SetIrq(com, irq) Set IRQ number (before open).
rs232SetMcr(com, mcr) Set modem control register directly.
rs232SetDtr(com, dtr) Set DTR line state.
rs232SetRts(com, rts) Set RTS line state.
rs232SetFifoThreshold(com, thr) Set FIFO trigger level (1, 4, 8, or 14 bytes).</pre>
<h2>Buffer Management</h2>
<pre> Function Description
-------- -----------
rs232ClearRxBuffer(com) Discard all data in the receive ring buffer.
rs232ClearTxBuffer(com) Discard all data in the transmit ring buffer.</pre>
</div>
<div class="topic" id="lib.serial.packet">
<h1>Packet Transport</h1>
<p>Reliable, ordered packet delivery over an RS-232 serial link. Uses HDLC-style byte-stuffed framing for frame delimiting, CRC-16-CCITT for error detection, and Go-Back-N ARQ with a configurable sliding window for retransmission.</p>
<p>Header: packet/packet.h</p>
<h2>Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
PKT_MAX_PAYLOAD 255 Maximum bytes per packet payload.
PKT_DEFAULT_WINDOW 4 Default sliding window size (unacknowledged frames in flight).
PKT_MAX_WINDOW 8 Maximum sliding window size.</pre>
<h2>Error Codes</h2>
<pre> Constant Value Description
-------- ----- -----------
PKT_SUCCESS 0 Operation succeeded.
PKT_ERR_INVALID_PORT -1 Invalid COM port index.
PKT_ERR_NOT_OPEN -2 Connection is not open.
PKT_ERR_WOULD_BLOCK -4 Operation would block.
PKT_ERR_OVERFLOW -5 Buffer overflow.
PKT_ERR_INVALID_PARAM -6 Invalid parameter (NULL handle, bad data pointer, length out of range).
PKT_ERR_TX_FULL -7 Transmit window is full (non-blocking send only).
PKT_ERR_NO_DATA -8 No data available.
PKT_ERR_DISCONNECTED -9 Serial port returned a negative read (disconnect/error).</pre>
<h2>PktRecvCallbackT</h2>
<p>Callback type for received packets.</p>
<pre><code>typedef void (*PktRecvCallbackT)(void *ctx,
const uint8_t *data, int len);</code></pre>
<pre> Parameter Description
--------- -----------
ctx User context pointer (passed to pktOpen).
data Payload bytes (valid only during the callback).
len Payload length.</pre>
<h2>pktOpen</h2>
<p>Open a packetized connection over an already-open COM port. Only one packet connection may exist on a given COM port at a time; a second pktOpen call on the same port returns NULL to avoid silent framing corruption.</p>
<pre><code>PktConnT *pktOpen(int com, int windowSize,
PktRecvCallbackT callback, void *callbackCtx);</code></pre>
<pre> Parameter Description
--------- -----------
com COM port index (RS232_COM1..RS232_COM4). Must already be open via rs232Open.
windowSize Sliding window size (1..PKT_MAX_WINDOW). Pass 0 for PKT_DEFAULT_WINDOW. Values greater than PKT_MAX_WINDOW are clamped.
callback Called when a complete, CRC-verified, in-order packet is received. The data pointer is valid only during the callback.
callbackCtx User pointer passed to the callback.</pre>
<p>Returns an opaque PktConnT handle, or NULL on failure (invalid port, duplicate open, or allocation failure).</p>
<h2>pktClose</h2>
<p>Close a packetized connection and release its registry slot. Does not close the underlying COM port. The caller is responsible for calling rs232Close separately when no longer needed.</p>
<pre><code>void pktClose(PktConnT *conn);</code></pre>
<h2>pktSend</h2>
<p>Send a data packet. The payload is copied into an internal retransmit slot before transmission, so the caller may reuse the supplied buffer immediately.</p>
<pre><code>int pktSend(PktConnT *conn, const uint8_t *data,
int len, bool block);</code></pre>
<pre> Parameter Description
--------- -----------
conn Connection handle from pktOpen.
data Payload bytes (1..PKT_MAX_PAYLOAD).
len Payload length.
block If true, poll pktPoll internally until transmit window has space. If false, return PKT_ERR_TX_FULL immediately when the window is full.</pre>
<p>Returns PKT_SUCCESS on success, PKT_ERR_INVALID_PARAM for NULL/out-of-range input, PKT_ERR_TX_FULL for a non-blocking call with a full window, or PKT_ERR_DISCONNECTED if the serial port drops during a blocking wait.</p>
<h2>pktPoll</h2>
<p>Poll for incoming data, process received frames, and handle retransmits. Must be called frequently in the main loop. The callback is invoked synchronously for each complete, CRC-verified, in-order data frame, so the caller should be prepared for reentrant pktSend calls from within the callback.</p>
<pre><code>int pktPoll(PktConnT *conn);</code></pre>
<p>Returns the number of valid data packets delivered to the callback this call, or PKT_ERR_INVALID_PARAM if conn is NULL, or PKT_ERR_DISCONNECTED if the serial layer returned a negative read.</p>
<h2>pktReset</h2>
<p>Reset the local connection state (sequence numbers, transmit slots, RX state machine) and send a RST frame to the remote side. The remote's RST handler clears its own state and echoes a RST back. Useful for recovering from a desynchronized connection.</p>
<pre><code>int pktReset(PktConnT *conn);</code></pre>
<p>Returns PKT_SUCCESS on success or PKT_ERR_INVALID_PARAM if conn is NULL.</p>
<h2>pktCanSend</h2>
<p>Check whether there is room in the transmit window for another packet. Returns false when conn is NULL or the transmit window is full.</p>
<pre><code>bool pktCanSend(PktConnT *conn);</code></pre>
<h2>pktGetPending</h2>
<p>Get the number of unacknowledged packets currently in the transmit window. Ranges from 0 (all sent packets acknowledged) to windowSize (window full).</p>
<pre><code>int pktGetPending(PktConnT *conn);</code></pre>
<p>Returns the pending count on success, or PKT_ERR_INVALID_PARAM if conn is NULL.</p>
</div>
<div class="topic" id="lib.serial.security">
<h1>Security (DH + XTEA)</h1>
<p>Cryptographic primitives for the serial stack: 1024-bit Diffie-Hellman key exchange (RFC 2409 Group 2), XTEA block cipher in CTR mode, and an XTEA-CTR DRBG random number generator.</p>
<p>XTEA requires no lookup tables and compiles to approximately 20 instructions per round, making it suitable for 486-class hardware where AES S-box tables would thrash the 8KB cache.</p>
<p>Header: security/security.h</p>
<h2>Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
SEC_DH_KEY_SIZE 128 Size of a DH public key in bytes (1024 bits).
SEC_XTEA_KEY_SIZE 16 Size of an XTEA key in bytes (128 bits).</pre>
<h2>Error Codes</h2>
<pre> Constant Value Description
-------- ----- -----------
SEC_SUCCESS 0 Operation succeeded.
SEC_ERR_PARAM -1 Invalid parameter.
SEC_ERR_NOT_READY -2 DH context not ready (keys not generated or secret not computed).
SEC_ERR_ALLOC -3 Memory allocation failed.</pre>
<h2>RNG Functions</h2>
<p>The RNG uses XTEA-CTR as a DRBG. Hardware entropy from PIT timer jitter is weak (~20 bits); supplement with keyboard timing or mouse jitter before generating DH keys.</p>
<pre><code>void secRngSeed(const uint8_t *entropy, int len);
int secRngGatherEntropy(uint8_t *buf, int len);
void secRngAddEntropy(const uint8_t *data, int len);
void secRngBytes(uint8_t *buf, int len);</code></pre>
<pre> Function Description
-------- -----------
secRngSeed Seed the DRBG from an entropy buffer.
secRngGatherEntropy Gather hardware entropy (PIT jitter, BIOS tick count) into a buffer.
secRngAddEntropy Mix additional entropy into the DRBG state.
secRngBytes Generate pseudorandom bytes.</pre>
<h2>Diffie-Hellman Key Exchange</h2>
<p>1024-bit DH with 256-bit private exponents using the RFC 2409 Group 2 safe prime.</p>
<pre><code>SecDhT *secDhCreate(void);
int secDhGenerateKeys(SecDhT *dh);
int secDhGetPublicKey(SecDhT *dh, uint8_t *buf, int *len);
int secDhComputeSecret(SecDhT *dh,
const uint8_t *remotePub, int len);
int secDhDeriveKey(SecDhT *dh, uint8_t *key, int keyLen);
void secDhDestroy(SecDhT *dh);</code></pre>
<pre> Function Description
-------- -----------
secDhCreate Allocate a new DH context.
secDhGenerateKeys Generate a private exponent and public key. RNG must be seeded first.
secDhGetPublicKey Copy the local public key into buf. *len receives the key size.
secDhComputeSecret Compute the shared secret from the remote public key.
secDhDeriveKey Derive a symmetric key (XTEA key) from the shared secret via hashing.
secDhDestroy Free the DH context and all associated memory.</pre>
<p>Typical usage order: secDhCreate, secDhGenerateKeys, exchange public keys, secDhComputeSecret, secDhDeriveKey, secDhDestroy.</p>
<h2>XTEA-CTR Cipher</h2>
<p>XTEA in counter mode. Encrypt and decrypt are the same operation (XOR with keystream). The counter must never repeat with the same key.</p>
<pre><code>SecCipherT *secCipherCreate(const uint8_t *key);
void secCipherSetNonce(SecCipherT *c,
uint32_t nonceLo, uint32_t nonceHi);
void secCipherCrypt(SecCipherT *c,
uint8_t *data, int len);
void secCipherDestroy(SecCipherT *c);</code></pre>
<pre> Function Description
-------- -----------
secCipherCreate Allocate a cipher context with a 128-bit key. Returns NULL on allocation failure or NULL key. Initial counter is zero.
secCipherSetNonce Set the initial counter value (nonce). Must be unique per session. Both the stored nonce and the running counter are set to (nonceLo, nonceHi).
secCipherCrypt Encrypt or decrypt data in place. The counter increments by one every 8 bytes (one XTEA block).
secCipherDestroy Securely zero the cipher context (key and counter state) and free its memory.</pre>
<p>secCipherCreate returns NULL if the key pointer is NULL or allocation fails. secCipherCrypt is a no-op when any of c/data is NULL or len &lt;= 0.</p>
</div>
<div class="topic" id="lib.serial.seclink">
<h1>Secure Link</h1>
<p>Top-level API composing all three lower layers (rs232, packet, security) into a single interface. Provides channel multiplexing (0-127) and per-packet encryption control over a reliable serial link.</p>
<p>Each packet carries a one-byte header: bit 7 is the encrypted flag, bits 6..0 are the channel number. Unencrypted packets can be sent before the handshake completes (e.g., for version negotiation).</p>
<p>Header: seclink/secLink.h</p>
<h2>Constants</h2>
<pre> Constant Value Description
-------- ----- -----------
SECLINK_MAX_PAYLOAD 254 Maximum plaintext bytes per send (PKT_MAX_PAYLOAD minus 1-byte channel header).
SECLINK_MAX_CHANNEL 127 Highest valid channel number.
SECLINK_NUM_CHANNELS 128 Array size needed to hold one slot per channel (SECLINK_MAX_CHANNEL + 1).
SECLINK_CHAN_BUF_SIZE 4096 Recommended per-channel receive buffer size for callers that buffer inbound data between the receive callback and an application read.</pre>
<h2>Error Codes</h2>
<pre> Constant Value Description
-------- ----- -----------
SECLINK_SUCCESS 0 Operation succeeded.
SECLINK_ERR_PARAM -1 Invalid parameter (NULL pointer, bad channel, bad length).
SECLINK_ERR_SERIAL -2 RS-232 layer error.
SECLINK_ERR_ALLOC -3 Memory allocation failed.
SECLINK_ERR_HANDSHAKE -4 DH handshake failed (key generation, send, or disconnect during exchange).
SECLINK_ERR_NOT_READY -5 Handshake not yet completed (encrypted send attempted).
SECLINK_ERR_SEND -6 Packet send failed, or non-blocking send when window is full.</pre>
<h2>SecLinkRecvT</h2>
<p>Receive callback type. Delivers decrypted plaintext with the channel number.</p>
<pre><code>typedef void (*SecLinkRecvT)(void *ctx,
const uint8_t *data, int len, uint8_t channel);</code></pre>
<h2>secLinkOpen</h2>
<p>Open a secure serial link. Opens the COM port via rs232Open and creates a packet layer (default window size) with an internal receive dispatcher. The handshake must be performed separately via secLinkHandshake before encrypted data can be sent.</p>
<pre><code>SecLinkT *secLinkOpen(int com, int32_t bps, int dataBits,
char parity, int stopBits, int handshake,
SecLinkRecvT callback, void *ctx);</code></pre>
<pre> Parameter Description
--------- -----------
com COM port index (RS232_COM1..RS232_COM4).
bps Baud rate.
dataBits Data bits per character (5-8).
parity Parity mode ('N', 'O', 'E', 'M', 'S' or lowercase).
stopBits Stop bits (1 or 2).
handshake Flow control mode (RS232_HANDSHAKE_*).
callback Called when a packet is received, after decryption if applicable. Plaintext data pointer is valid only during the callback.
ctx User pointer passed to the callback.</pre>
<p>Returns an opaque SecLinkT handle, or NULL on failure (allocation failure, rs232Open error, or pktOpen error). On failure all partially initialized resources are cleaned up.</p>
<h2>secLinkClose</h2>
<p>Close the link and free all associated resources in reverse of open order: securely destroy TX and RX ciphers (which scrubs key material), destroy any remaining DH context, close the packet layer, close the COM port, and finally free the link struct itself. Safe to call with a NULL link (no-op).</p>
<pre><code>void secLinkClose(SecLinkT *link);</code></pre>
<h2>secLinkHandshake</h2>
<p>Perform a Diffie-Hellman key exchange and derive the session cipher keys. Blocks, polling the packet layer in a loop, until both sides have swapped public keys. The RNG must be seeded (via secRngSeed, secRngGatherEntropy + secRngSeed, or secRngAddEntropy) before calling this, or the generated private key will be predictable.</p>
<pre><code>int secLinkHandshake(SecLinkT *link);</code></pre>
<p>Internally:</p>
<ul>
<li>Creates a DH context via secDhCreate, generates 1024-bit keys via secDhGenerateKeys, and exports the 128-byte public key.</li>
<li>Sends the public key as a single packet via pktSend (blocking).</li>
</ul>
<p>Polls pktPoll until the remote's public key arrives and the internal callback completes the handshake (computes the shared secret, derives directional TX and RX cipher keys, transitions to READY, destroys the DH context for forward secrecy).</p>
<p>Returns SECLINK_SUCCESS on success, SECLINK_ERR_PARAM on NULL link, SECLINK_ERR_ALLOC on DH context allocation failure, or SECLINK_ERR_HANDSHAKE for DH key generation failure, packet send failure, or serial disconnect during the exchange.</p>
<h3>Directional Key Derivation</h3>
<p>To prevent CTR-mode keystream collision, the two sides never use the same TX key. After computing the shared secret, each side derives a master XTEA key via secDhDeriveKey and then XORs it with a direction byte:</p>
<ul>
<li>The side with the lexicographically lower public key uses masterKey XOR 0xAA for TX and masterKey XOR 0x55 for RX.</li>
</ul>
<p>The other side uses the reverse assignment.</p>
<p>Both sides initialize their cipher counters to zero and advance monotonically from there.</p>
<h2>secLinkSend</h2>
<p>Send data on a channel, optionally encrypted. Prepends a one-byte channel header (bit 7 = encrypt flag, bits 6..0 = channel number), then encrypts the payload only (never the header) when encrypt is true.</p>
<pre><code>int secLinkSend(SecLinkT *link, const uint8_t *data,
int len, uint8_t channel, bool encrypt, bool block);</code></pre>
<pre> Parameter Description
--------- -----------
link Connection handle from secLinkOpen.
data Plaintext payload (1..SECLINK_MAX_PAYLOAD bytes).
len Payload length. Must be in 1..SECLINK_MAX_PAYLOAD.
channel Logical channel number (0..SECLINK_MAX_CHANNEL).
encrypt If true, encrypt before sending (requires completed handshake).
block If true, block until the transmit window has space. If false, return SECLINK_ERR_SEND immediately when the window is full.</pre>
<p>Returns SECLINK_SUCCESS on success or a negative error code (SECLINK_ERR_PARAM, SECLINK_ERR_NOT_READY, SECLINK_ERR_SEND).</p>
<p>Cipher counter safety: the function checks transmit window space BEFORE encrypting the payload. Encrypting first and then failing to send would advance the TX cipher counter while the data never reached the wire, permanently desynchronizing the TX cipher state from the remote's RX cipher. This ordering is critical for correctness when non-blocking sends are used.</p>
<h2>secLinkSendBuf</h2>
<p>Send an arbitrarily large buffer by splitting into SECLINK_MAX_PAYLOAD chunks. Always blocks until all data is sent.</p>
<pre><code>int secLinkSendBuf(SecLinkT *link, const uint8_t *data,
int len, uint8_t channel, bool encrypt);</code></pre>
<p>Returns SECLINK_SUCCESS or the first error encountered.</p>
<h2>secLinkPoll</h2>
<p>Poll for incoming data. Delegates to pktPoll, which drains the RS-232 ring buffer, processes received frames, checks retransmit timers, and dispatches each complete packet to an internal callback that strips the channel header, decrypts when the encrypt flag is set, and forwards plaintext to the user callback.</p>
<pre><code>int secLinkPoll(SecLinkT *link);</code></pre>
<p>Returns the number of packets delivered to the callback this call, SECLINK_ERR_PARAM if link is NULL, or one of the pktPoll error codes (PKT_ERR_DISCONNECTED, PKT_ERR_INVALID_PARAM). Must be called frequently in the main loop.</p>
<h2>secLinkIsReady</h2>
<p>Check whether the handshake is complete and the link is ready for encrypted traffic. Cleartext sends do not require the link to be ready.</p>
<pre><code>bool secLinkIsReady(SecLinkT *link);</code></pre>
<p>Returns true only when link is non-NULL and the internal state is STATE_READY (that is, secLinkHandshake has completed). Returns false on NULL or before the handshake.</p>
<h2>secLinkGetPending</h2>
<p>Get the number of unacknowledged packets in the transmit window. Delegates directly to pktGetPending on the underlying packet connection. Useful for non-blocking send loops to decide when to throttle.</p>
<pre><code>int secLinkGetPending(SecLinkT *link);</code></pre>
<p>Returns the pending count on success or SECLINK_ERR_PARAM when link is NULL.</p>
</div>
<div class="topic" id="lib.serial.example">
<h1>End-to-End Example</h1>
<p>Below is a complete secure BBS client that opens COM1, exchanges DH keys, and then shuttles terminal traffic over a single encrypted channel. It demonstrates the typical serial stack usage: open the link, seed the RNG, run the handshake, then enter a poll+send loop.</p>
<pre><code>#include &quot;rs232/rs232.h&quot;
#include &quot;packet/packet.h&quot;
#include &quot;security/security.h&quot;
#include &quot;seclink/secLink.h&quot;
#include &lt;stdio.h&gt;
#include &lt;string.h&gt;
#define CHAN_TERMINAL 0
static void onPacket(void *ctx, const uint8_t *data,
int len, uint8_t channel)
{
(void)ctx;
if (channel == CHAN_TERMINAL) {
fwrite(data, 1, len, stdout);
fflush(stdout);
}
}
int main(void) {
// Seed the RNG from hardware entropy plus any user-derived
// randomness (keyboard timing, etc.).
uint8_t entropy[16];
int got = secRngGatherEntropy(entropy, sizeof(entropy));
secRngSeed(entropy, got);
// Open the link at 115200 8N1 with RTS/CTS flow control.
SecLinkT *link = secLinkOpen(
RS232_COM1, 115200, 8, 'N', 1,
RS232_HANDSHAKE_RTSCTS,
onPacket, NULL);
if (!link) {
fprintf(stderr, &quot;secLinkOpen failed\n&quot;);
return 1;
}
// Run the DH key exchange. Blocks until both sides
// have swapped public keys and derived cipher keys.
if (secLinkHandshake(link) != SECLINK_SUCCESS) {
fprintf(stderr, &quot;Handshake failed\n&quot;);
secLinkClose(link);
return 1;
}
// Send an encrypted banner and then relay keyboard input.
const char *hello = &quot;Hello, secure BBS!\r\n&quot;;
secLinkSend(link, (const uint8_t *)hello,
(int)strlen(hello), CHAN_TERMINAL, true, true);
while (!feof(stdin)) {
// Deliver any incoming packets to onPacket().
secLinkPoll(link);
// If the user typed something, forward it encrypted.
int ch = getchar();
if (ch == EOF) {
break;
}
uint8_t byte = (uint8_t)ch;
secLinkSend(link, &amp;byte, 1, CHAN_TERMINAL, true, true);
}
secLinkClose(link);
return 0;
}</code></pre>
<p>Notes:</p>
<ul>
<li>secLinkOpen internally calls rs232Open and pktOpen. secLinkClose tears them down in reverse order.</li>
<li>The RNG must be seeded before secLinkHandshake. secRngGatherEntropy provides roughly 20 bits of hardware entropy; supplement with user interaction timing for cryptographic use.</li>
<li>secLinkPoll must be called frequently to drain the RX ring buffer, process ACKs, and dispatch received packets to the callback.</li>
</ul>
<p>For bulk transfers larger than SECLINK_MAX_PAYLOAD (254 bytes), use secLinkSendBuf which splits the data into chunks automatically.</p>
</div>
<div class="topic" id="lib.basrt">
<h1>BASIC Runtime Library</h1>
<p>Stack-based p-code virtual machine and value system for DVX BASIC. Embeddable: the host provides I/O and UI callbacks. No DVX GUI dependencies in the core runtime.</p>
<p>Headers: apps/dvxbasic/runtime/vm.h, apps/dvxbasic/runtime/values.h</p>
<p><a href="#lib.basrt.values">Value System (values.h)</a></p>
<p><a href="#lib.basrt.vm">Virtual Machine (vm.h)</a></p>
</div>
<div class="topic" id="lib.basrt.values">
<h1>Value System</h1>
<p>Tagged union value type for the VM evaluation stack, variables, and array elements. Strings, arrays, and UDT instances are reference-counted for automatic memory management without a garbage collector.</p>
<p>Header: apps/dvxbasic/runtime/values.h</p>
<h2>Type Tags</h2>
<pre> Constant Value C Union Field Description
-------- ----- ------------- -----------
BAS_TYPE_INTEGER 0 intVal 16-bit signed integer.
BAS_TYPE_LONG 1 longVal 32-bit signed integer.
BAS_TYPE_SINGLE 2 sngVal 32-bit float.
BAS_TYPE_DOUBLE 3 dblVal 64-bit float.
BAS_TYPE_STRING 4 strVal Reference-counted dynamic string.
BAS_TYPE_BOOLEAN 5 boolVal True (-1) or False (0).
BAS_TYPE_ARRAY 6 arrVal Reference-counted array.
BAS_TYPE_UDT 7 udtVal Reference-counted user-defined type.
BAS_TYPE_OBJECT 8 objVal Opaque host pointer (form, control).
BAS_TYPE_REF 9 refVal ByRef pointer to a BasValueT slot.</pre>
<h2>BasValueT</h2>
<p>Tagged union holding any BASIC value.</p>
<pre><code>struct BasValueTag {
uint8_t type; // BAS_TYPE_*
union {
int16_t intVal;
int32_t longVal;
float sngVal;
double dblVal;
BasStringT *strVal;
int16_t boolVal;
BasArrayT *arrVal;
BasUdtT *udtVal;
void *objVal;
BasValueT *refVal;
};
};</code></pre>
<h2>Value Constructors</h2>
<pre><code>BasValueT basValInteger(int16_t v);
BasValueT basValLong(int32_t v);
BasValueT basValSingle(float v);
BasValueT basValDouble(double v);
BasValueT basValString(BasStringT *s);
BasValueT basValStringFromC(const char *text);
BasValueT basValBool(bool v);
BasValueT basValObject(void *obj);</code></pre>
<p>Each returns a BasValueT with the appropriate type tag set. basValString increments the string's reference count.</p>
<h2>Value Lifetime</h2>
<pre><code>BasValueT basValCopy(BasValueT v);
void basValRelease(BasValueT *v);</code></pre>
<pre> Function Description
-------- -----------
basValCopy Copy a value. Increments reference count for strings, arrays, and UDTs.
basValRelease Release a value. Decrements reference count and frees if it reaches zero.</pre>
<h2>Type Conversion</h2>
<pre><code>BasValueT basValToInteger(BasValueT v);
BasValueT basValToLong(BasValueT v);
BasValueT basValToSingle(BasValueT v);
BasValueT basValToDouble(BasValueT v);
BasValueT basValToString(BasValueT v);
BasValueT basValToBool(BasValueT v);</code></pre>
<p>Each returns a new value of the target type. The original is not released; the caller manages both lifetimes.</p>
<h2>Value Utilities</h2>
<pre> Function Description
-------- -----------
basValToNumber(v) Convert any numeric value to double.
basValFormatString(v) Return a new ref-counted string representation of v.
basValIsTruthy(v) True if non-zero number or non-empty string.
basValCompare(a, b) Compare two values. Returns -1, 0, or 1.
basValCompareCI(a, b) Case-insensitive comparison (OPTION COMPARE TEXT).
basValPromoteType(a, b) Determine common type for binary ops (e.g. Integer + Single -&gt; Single).</pre>
<h2>BasStringT</h2>
<p>Reference-counted string with flexible array member for inline storage.</p>
<pre><code>typedef struct {
int32_t refCount;
int32_t len;
int32_t cap;
char data[];
} BasStringT;</code></pre>
<h3>String Functions</h3>
<pre> Function Description
-------- -----------
basStringNew(text, len) Allocate from a C string. refCount starts at 1.
basStringAlloc(cap) Allocate an empty string with given capacity.
basStringRef(s) Increment reference count. Returns s.
basStringUnref(s) Decrement reference count. Frees when it reaches zero.
basStringConcat(a, b) Concatenate two strings. Returns a new string (refCount 1).
basStringSub(s, start, len) Extract a substring. Returns a new string (refCount 1).
basStringCompare(a, b) Compare. Returns &lt;0, 0, &gt;0 (like strcmp).
basStringCompareCI(a, b) Case-insensitive compare.
basStringSystemInit() Initialize the string system and empty string singleton.
basStringSystemShutdown() Shut down the string system.</pre>
<p>The global basEmptyString is a singleton that is never freed.</p>
<h2>BasArrayT</h2>
<p>Reference-counted multi-dimensional array (up to BAS_ARRAY_MAX_DIMS = 8 dimensions).</p>
<pre><code>typedef struct {
int32_t refCount;
uint8_t elementType;
int32_t dims;
int32_t lbound[BAS_ARRAY_MAX_DIMS];
int32_t ubound[BAS_ARRAY_MAX_DIMS];
int32_t totalElements;
BasValueT *elements;
} BasArrayT;</code></pre>
<h3>Array Functions</h3>
<pre> Function Description
-------- -----------
basArrayNew(dims, lbounds, ubounds, type) Allocate an array. refCount starts at 1.
basArrayFree(arr) Free all elements and release the array.
basArrayRef(arr) Increment reference count.
basArrayUnref(arr) Decrement reference count. Frees at zero.
basArrayIndex(arr, indices, ndims) Compute flat index from multi-dimensional indices. Returns -1 if out of bounds.</pre>
<h2>BasUdtT</h2>
<p>Reference-counted user-defined type instance.</p>
<pre><code>typedef struct {
int32_t refCount;
int32_t typeId;
int32_t fieldCount;
BasValueT *fields;
} BasUdtT;</code></pre>
<h3>UDT Functions</h3>
<pre> Function Description
-------- -----------
basUdtNew(typeId, fieldCount) Allocate a UDT instance. refCount starts at 1.
basUdtFree(udt) Free all fields and release.
basUdtRef(udt) Increment reference count.
basUdtUnref(udt) Decrement reference count. Frees at zero.</pre>
</div>
<div class="topic" id="lib.basrt.vm">
<h1>Virtual Machine</h1>
<p>Stack-based p-code interpreter. Executes compiled BASIC bytecode modules. The host provides I/O, UI, SQL, and external library callbacks. The VM has no DVX dependencies; it can be embedded in any C program.</p>
<p>Header: apps/dvxbasic/runtime/vm.h</p>
<h2>VM Limits</h2>
<pre> Constant Value Description
-------- ----- -----------
BAS_VM_STACK_SIZE 256 Evaluation stack depth.
BAS_VM_CALL_STACK_SIZE 64 Maximum call nesting depth.
BAS_VM_MAX_GLOBALS 512 Global variable slots.
BAS_VM_MAX_LOCALS 64 Local variables per stack frame.
BAS_VM_MAX_FOR_DEPTH 32 Maximum nested FOR loop depth.
BAS_VM_MAX_FILES 16 Open file channels (1-based).</pre>
<h2>BasVmResultE</h2>
<p>Result codes returned by basVmRun and basVmStep.</p>
<pre> Code Value Description
---- ----- -----------
BAS_VM_OK 0 Program completed normally.
BAS_VM_HALTED 1 HALT instruction reached.
BAS_VM_YIELDED 2 DoEvents yielded control.
BAS_VM_ERROR 3 Runtime error.
BAS_VM_STACK_OVERFLOW 4 Evaluation stack overflow.
BAS_VM_STACK_UNDERFLOW 5 Evaluation stack underflow.
BAS_VM_CALL_OVERFLOW 6 Call stack overflow.
BAS_VM_DIV_BY_ZERO 7 Division by zero.
BAS_VM_TYPE_MISMATCH 8 Type mismatch in operation.
BAS_VM_OUT_OF_MEMORY 9 Memory allocation failed.
BAS_VM_BAD_OPCODE 10 Unknown opcode encountered.
BAS_VM_FILE_ERROR 11 File I/O error.
BAS_VM_SUBSCRIPT_RANGE 12 Array subscript out of range.
BAS_VM_USER_ERROR 13 ON ERROR raised by program.
BAS_VM_STEP_LIMIT 14 Step limit reached (not an error).
BAS_VM_BREAKPOINT 15 Breakpoint or step completed (not an error).</pre>
<h2>Lifecycle</h2>
<pre><code>BasVmT *basVmCreate(void);
void basVmDestroy(BasVmT *vm);
void basVmLoadModule(BasVmT *vm, BasModuleT *module);
void basVmReset(BasVmT *vm);</code></pre>
<pre> Function Description
-------- -----------
basVmCreate Allocate and initialize a new VM instance.
basVmDestroy Destroy the VM and free all resources.
basVmLoadModule Load a compiled module (BasModuleT) into the VM.
basVmReset Reset to initial state (clear stack, globals, PC).</pre>
<h2>Execution</h2>
<pre><code>BasVmResultE basVmRun(BasVmT *vm);
BasVmResultE basVmStep(BasVmT *vm);
void basVmSetStepLimit(BasVmT *vm, int32_t limit);</code></pre>
<pre> Function Description
-------- -----------
basVmRun Execute the loaded module until it ends, halts, yields, errors, or hits a breakpoint/step limit.
basVmStep Execute a single instruction and return. Useful for debugger stepping.
basVmSetStepLimit Set maximum instructions per basVmRun call. 0 = unlimited (default). Returns BAS_VM_STEP_LIMIT when reached.</pre>
<h2>I/O Callbacks</h2>
<p>The host provides these callbacks for PRINT, INPUT, and DoEvents statements.</p>
<pre><code>void basVmSetPrintCallback(BasVmT *vm, BasPrintFnT fn, void *ctx);
void basVmSetInputCallback(BasVmT *vm, BasInputFnT fn, void *ctx);
void basVmSetDoEventsCallback(BasVmT *vm, BasDoEventsFnT fn, void *ctx);</code></pre>
<h3>Callback Types</h3>
<pre><code>typedef void (*BasPrintFnT)(void *ctx, const char *text, bool newline);
typedef bool (*BasInputFnT)(void *ctx, const char *prompt,
char *buf, int32_t bufSize);
typedef bool (*BasDoEventsFnT)(void *ctx);</code></pre>
<pre> Type Description
---- -----------
BasPrintFnT Called for PRINT output. text is null-terminated. newline indicates line advance.
BasInputFnT Called for INPUT. Fill buf (up to bufSize-1 chars). Return true on success, false on cancel.
BasDoEventsFnT Called for DoEvents. Process pending events and return. Return false to stop the program.</pre>
<h2>UI Callbacks</h2>
<p>For form and control integration. The VM resolves all UI operations through these callbacks, keeping it independent of any specific GUI toolkit.</p>
<pre><code>void basVmSetUiCallbacks(BasVmT *vm, const BasUiCallbacksT *ui);</code></pre>
<h3>BasUiCallbacksT</h3>
<pre> Field Signature Description
----- --------- -----------
getProp BasValueT (*)(ctx, ctrlRef, propName) Get a control property value.
setProp void (*)(ctx, ctrlRef, propName, value) Set a control property.
callMethod BasValueT (*)(ctx, ctrlRef, methodName, args, argc) Call a method on a control.
createCtrl void *(*)(ctx, formRef, typeName, ctrlName) Create a control on a form.
findCtrl void *(*)(ctx, formRef, ctrlName) Find a control by name.
findCtrlIdx void *(*)(ctx, formRef, ctrlName, index) Find a control array element.
loadForm void *(*)(ctx, formName) Load a form by name.
unloadForm void (*)(ctx, formRef) Unload a form.
showForm void (*)(ctx, formRef, modal) Show a form (modal or modeless).
hideForm void (*)(ctx, formRef) Hide a form (keep in memory).
msgBox int32_t (*)(ctx, message, flags) Display a message box.
inputBox BasStringT *(*)(ctx, prompt, title, defaultText) Display an input box.
ctx void * User pointer passed to all callbacks.</pre>
<h2>SQL Callbacks</h2>
<p>For database integration.</p>
<pre><code>void basVmSetSqlCallbacks(BasVmT *vm, const BasSqlCallbacksT *sql);</code></pre>
<h3>BasSqlCallbacksT</h3>
<pre> Field Signature Description
----- --------- -----------
sqlOpen int32_t (*)(path) Open a database. Returns handle.
sqlClose void (*)(db) Close a database.
sqlExec bool (*)(db, sql) Execute a non-query SQL statement.
sqlError const char *(*)(db) Get last error message.
sqlQuery int32_t (*)(db, sql) Execute a query. Returns result set handle.
sqlNext bool (*)(rs) Advance to next row.
sqlEof bool (*)(rs) Check if at end of result set.
sqlFieldCount int32_t (*)(rs) Get number of columns.
sqlFieldName const char *(*)(rs, col) Get column name by index.
sqlFieldText const char *(*)(rs, col) Get column value as text by index.
sqlFieldByName const char *(*)(rs, name) Get column value as text by name.
sqlFieldInt int32_t (*)(rs, col) Get column value as integer.
sqlFieldDbl double (*)(rs, col) Get column value as double.
sqlFreeResult void (*)(rs) Free a result set.
sqlAffectedRows int32_t (*)(db) Get number of rows affected by last statement.</pre>
<h2>External Library Callbacks</h2>
<p>For DECLARE LIBRARY support. The VM resolves external functions at runtime via the host.</p>
<pre><code>void basVmSetExternCallbacks(BasVmT *vm,
const BasExternCallbacksT *ext);</code></pre>
<h3>BasExternCallbacksT</h3>
<pre> Field Signature Description
----- --------- -----------
resolveExtern void *(*)(ctx, libName, funcName) Resolve a native function by library and symbol name. Cached after first call.
callExtern BasValueT (*)(ctx, funcPtr, funcName, args, argc, retType) Call a resolved native function, marshalling arguments and return value.
ctx void * User pointer passed to both callbacks.</pre>
<h2>Form Context</h2>
<p>Set the active form context during event dispatch.</p>
<pre><code>void basVmSetCurrentForm(BasVmT *vm, void *formRef);
void basVmSetCurrentFormVars(BasVmT *vm,
BasValueT *vars, int32_t count);</code></pre>
<h2>Stack Access</h2>
<p>Push and pop values on the evaluation stack for host integration.</p>
<pre><code>bool basVmPush(BasVmT *vm, BasValueT val);
bool basVmPop(BasVmT *vm, BasValueT *val);</code></pre>
<p>Both return true on success, false on stack overflow/underflow.</p>
<h2>Error Reporting</h2>
<pre><code>const char *basVmGetError(const BasVmT *vm);</code></pre>
<p>Returns the current error message string. Valid after basVmRun returns BAS_VM_ERROR.</p>
<h2>Sub/Function Calls from Host</h2>
<p>Call a SUB or FUNCTION by its code address from host code.</p>
<pre><code>bool basVmCallSub(BasVmT *vm, int32_t codeAddr);
bool basVmCallSubWithArgs(BasVmT *vm, int32_t codeAddr,
const BasValueT *args, int32_t argCount);
bool basVmCallSubWithArgsOut(BasVmT *vm, int32_t codeAddr,
const BasValueT *args, int32_t argCount,
BasValueT *outArgs, int32_t outCount);</code></pre>
<pre> Function Description
-------- -----------
basVmCallSub Call a SUB with no arguments.
basVmCallSubWithArgs Call a SUB with arguments pushed onto the stack frame.
basVmCallSubWithArgsOut Call a SUB and read back modified argument values after it returns.</pre>
<p>All three push a call frame, execute until the SUB returns, then restore the previous execution state. Return true on normal completion, false on error or if the VM is not idle.</p>
<h2>Debugger API</h2>
<pre><code>void basVmSetBreakpoints(BasVmT *vm,
int32_t *lines, int32_t count);
void basVmStepInto(BasVmT *vm);
void basVmStepOver(BasVmT *vm);
void basVmStepOut(BasVmT *vm);
void basVmRunToCursor(BasVmT *vm, int32_t line);
int32_t basVmGetCurrentLine(const BasVmT *vm);</code></pre>
<pre> Function Description
-------- -----------
basVmSetBreakpoints Set the breakpoint list (sorted array of source line numbers, host-owned memory).
basVmStepInto Break at the next OP_LINE instruction.
basVmStepOver Break when call depth returns to the current level.
basVmStepOut Break when call depth drops below the current level.
basVmRunToCursor Break when execution reaches the specified source line.
basVmGetCurrentLine Get the current source line number (from the last OP_LINE instruction).</pre>
<p>The breakpoint callback notifies the host when a breakpoint fires during nested sub calls:</p>
<pre><code>typedef void (*BasBreakpointFnT)(void *ctx, int32_t line);</code></pre>
<h2>BasModuleT</h2>
<p>Compiled module produced by the BASIC compiler and loaded into the VM.</p>
<pre><code>typedef struct {
uint8_t *code;
int32_t codeLen;
BasStringT **constants;
int32_t constCount;
int32_t globalCount;
int32_t entryPoint;
BasValueT *dataPool;
int32_t dataCount;
BasProcEntryT *procs;
int32_t procCount;
BasFormVarInfoT *formVarInfo;
int32_t formVarInfoCount;
BasDebugVarT *debugVars;
int32_t debugVarCount;
BasDebugUdtDefT *debugUdtDefs;
int32_t debugUdtDefCount;
} BasModuleT;</code></pre>
<pre> Field Description
----- -----------
code P-code bytecode array.
codeLen Length of bytecode in bytes.
constants String constant pool.
constCount Number of string constants.
globalCount Number of global variable slots needed.
entryPoint PC of the first instruction (module-level code).
dataPool DATA statement value pool (for READ).
dataCount Number of values in the data pool.
procs Procedure table (SUBs and FUNCTIONs).
procCount Number of procedures.
formVarInfo Per-form variable counts and init code addresses.
formVarInfoCount Number of forms with form-scoped variables.
debugVars Variable names and metadata for the debugger.
debugVarCount Number of debug variable entries.
debugUdtDefs UDT type definitions for the debugger.
debugUdtDefCount Number of debug UDT definitions.</pre>
</div>
<div class="topic" id="widget.base">
<h1>DVX Widget System</h1>
<p>Complete reference for the DVX GUI widget toolkit. All widgets are implemented as dynamically loaded DXE modules. They are created via convenience macros that wrap the per-widget API function tables. The base WidgetT structure is defined in libdvx/dvxWgt.h; individual widget headers live in widgets/.</p>
<p>Individual widgets are documented in their own sections. See the table of contents for the full list.</p>
<h2>Base WidgetT (Common Properties, Events, and Operations)</h2>
<p>Every widget inherits from the WidgetT structure defined in libdvx/dvxWgt.h. The fields and callbacks listed here are available on all widget types.</p>
<h3>Common Properties</h3>
<pre> Field Type Description
----- ---- -----------
name char[32] Widget name for lookup via wgtFind().
x, y, w, h int32_t Computed geometry relative to the window content area (set by layout).
minW, minH int32_t (tagged) Minimum size hints. Use wgtPixels(), wgtChars(), or wgtPercent(). 0 = auto.
maxW, maxH int32_t (tagged) Maximum size constraints. 0 = no limit.
prefW, prefH int32_t (tagged) Preferred size. 0 = auto.
weight int32_t Extra-space distribution weight. 0 = fixed, 100 = normal. A widget with weight=200 gets twice the extra space of one with weight=100.
align WidgetAlignE Main-axis alignment for children: AlignStartE, AlignCenterE, AlignEndE.
spacing int32_t (tagged) Spacing between children (containers only). 0 = default.
padding int32_t (tagged) Internal padding (containers only). 0 = default.
fgColor uint32_t Foreground color override. 0 = use color scheme default.
bgColor uint32_t Background color override. 0 = use color scheme default.
visible bool Visibility state.
enabled bool Enabled state. Disabled widgets are grayed out and ignore input.
readOnly bool Read-only mode: allows scrolling/selection but blocks editing.
swallowTab bool When true, Tab key goes to the widget instead of navigating focus.
accelKey char Lowercase accelerator character. 0 if none.
tooltip const char * Tooltip text. NULL = none. Caller owns the string.
contextMenu MenuT * Right-click context menu. NULL = none. Caller owns.
userData void * Application-defined user data pointer.</pre>
<h3>Size Specification Macros</h3>
<pre> Macro Description
----- -----------
wgtPixels(v) Size in pixels.
wgtChars(v) Size in character widths (multiplied by font charWidth).
wgtPercent(v) Size as a percentage of parent dimension.</pre>
<h3>Common Events (Callbacks)</h3>
<p>These callback function pointers are available on every WidgetT. Set them directly on the widget struct.</p>
<pre> Callback Signature Description
-------- --------- -----------
onClick void (*)(WidgetT *w) Fires on mouse click / activation.
onDblClick void (*)(WidgetT *w) Fires on double-click.
onChange void (*)(WidgetT *w) Fires when the widget's value changes (text, selection, check state, etc.).
onFocus void (*)(WidgetT *w) Fires when the widget receives keyboard focus.
onBlur void (*)(WidgetT *w) Fires when the widget loses keyboard focus.
onKeyPress void (*)(WidgetT *w, int32_t keyAscii) Fires on a printable key press (ASCII value).
onKeyDown void (*)(WidgetT *w, int32_t keyCode, int32_t shift) Fires on key down (scan code + shift state).
onKeyUp void (*)(WidgetT *w, int32_t keyCode, int32_t shift) Fires on key up.
onMouseDown void (*)(WidgetT *w, int32_t button, int32_t x, int32_t y) Fires on mouse button press.
onMouseUp void (*)(WidgetT *w, int32_t button, int32_t x, int32_t y) Fires on mouse button release.
onMouseMove void (*)(WidgetT *w, int32_t button, int32_t x, int32_t y) Fires on mouse movement over the widget.
onScroll void (*)(WidgetT *w, int32_t delta) Fires on mouse wheel scroll.
onValidate bool (*)(WidgetT *w) Validation callback. Return false to cancel a pending write.</pre>
<h3>Common Operations</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtInitWindow(AppContextT *ctx, WindowT *win) Initialize widgets for a window. Returns the root VBox container.
AppContextT *wgtGetContext(const WidgetT *w) Walk up from any widget to retrieve the AppContextT.
void wgtInvalidate(WidgetT *w) Mark widget for re-layout and repaint. Propagates to ancestors.
void wgtInvalidatePaint(WidgetT *w) Mark widget for repaint only (no layout recalculation).
void wgtSetText(WidgetT *w, const char *text) Set widget text (label, button, textinput, etc.).
const char *wgtGetText(const WidgetT *w) Get widget text.
void wgtSetEnabled(WidgetT *w, bool enabled) Enable or disable a widget.
void wgtSetReadOnly(WidgetT *w, bool readOnly) Set read-only mode.
void wgtSetFocused(WidgetT *w) Set keyboard focus to a widget.
WidgetT *wgtGetFocused(void) Get the currently focused widget.
void wgtSetVisible(WidgetT *w, bool visible) Show or hide a widget.
void wgtSetName(WidgetT *w, const char *name) Set widget name for lookup.
WidgetT *wgtFind(WidgetT *root, const char *name) Find a widget by name in the subtree.
void wgtDestroy(WidgetT *w) Destroy a widget and all its children.
void wgtSetTooltip(WidgetT *w, const char *text) Set tooltip text. Pass NULL to remove.</pre>
</div>
<div class="topic" id="widget.ansiterm">
<h2>AnsiTerm</h2>
<p>A VT100/ANSI-compatible terminal emulator widget designed for connecting to BBS systems over the serial link. Uses a traditional text-mode cell buffer (character + attribute byte pairs) with the CP437 character set and 16-color CGA palette. Supports cursor movement, screen/line erase, scrolling regions, SGR colors, DEC private modes, and a configurable scrollback buffer. Communication is abstracted through read/write function pointers, allowing the terminal to work with raw serial ports, the secLink encrypted channel, or any other byte-oriented transport.</p>
<p>The widget renders through two paint paths: a full paint used by the normal widget pipeline, and a fast incremental repaint (wgtAnsiTermRepaint) that pushes dirty rows directly to the window content buffer for low-latency serial echo.</p>
<p>Header: widgets/ansiTerm.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *term = wgtAnsiTerm(parent, 80, 25);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtAnsiTerm(parent, cols, rows) Create an ANSI terminal widget with the given column/row dimensions.
void wgtAnsiTermWrite(w, data, len) Write raw bytes into the terminal's ANSI parser. data is a const uint8_t * buffer.
void wgtAnsiTermClear(w) Clear the terminal screen and reset the cursor to the home position.
void wgtAnsiTermSetComm(w, ctx, readFn, writeFn) Attach a communication channel. readFn and writeFn are I/O callbacks; ctx is passed as their first argument.
void wgtAnsiTermSetScrollback(w, maxLines) Set the maximum number of scrollback lines.
int32_t wgtAnsiTermPoll(w) Poll the communication channel for incoming data and feed it into the parser. Returns number of bytes consumed.
int32_t wgtAnsiTermRepaint(w, outY, outH) Fast repaint path that renders dirty rows directly into the window's content buffer, bypassing the widget pipeline. Returns the number of rows repainted and the dirty region via outY/outH.</pre>
<h3>API Struct (wgtRegisterApi &quot;ansiterm&quot;)</h3>
<p>The sApi struct exposes these function pointers:</p>
<pre> Slot Function
---- --------
create wgtAnsiTerm
write wgtAnsiTermWrite
clear wgtAnsiTermClear
setComm wgtAnsiTermSetComm
setScrollback wgtAnsiTermSetScrollback
poll wgtAnsiTermPoll
repaint wgtAnsiTermRepaint</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Cols Integer Read-only Number of columns.
Rows Integer Read-only Number of rows.
Scrollback Integer Write-only Maximum number of scrollback lines.</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
Clear Clear the terminal screen.
Poll Process any pending bytes on the attached communication channel.
Write Write a string into the terminal (with ANSI escape processing).</pre>
<h3>Events</h3>
<p>AnsiTerm uses the common events only. No widget-specific events are defined.</p>
<h3>Keyboard Shortcuts</h3>
<p>Within the terminal widget:</p>
<pre> Key Action
--- ------
Ctrl+C Copy selection to the clipboard (when a selection exists).
Ctrl+V Send the clipboard contents to the attached write function.
Arrows Send VT100 cursor escape sequences.
Home/End Send VT100 Home/End sequences.
PgUp/PgDn/Del Send the corresponding VT100 escape sequences.</pre>
</div>
<div class="topic" id="widget.box">
<h2>Box (VBox / HBox / Frame)</h2>
<p>Container widgets that arrange their children in a vertical column (VBox), horizontal row (HBox), or a titled group box (Frame). These are the primary layout building blocks. Children are laid out using a weight-based algorithm with configurable spacing, padding, and alignment.</p>
<p>Frame is a labelled grouping container with a Motif-style beveled border. Its title text sits centered vertically on the top border line with a small background-filled gap behind the title, giving the classic Windows 3.1 / Motif group box appearance. Internally, Frame behaves like a VBox for layout purposes.</p>
<p>The widget DXE registers three separate interface entries (&quot;vbox&quot;, &quot;hbox&quot;, &quot;frame&quot;) so the form designer can create each type independently.</p>
<p>Header: widgets/box.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *row = wgtHBox(parent);
WidgetT *col = wgtVBox(parent);
WidgetT *group = wgtFrame(parent, &quot;Options&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtVBox(parent) Create a vertical box container. Children stack top-to-bottom.
WidgetT *wgtHBox(parent) Create a horizontal box container. Children stack left-to-right.
WidgetT *wgtFrame(parent, title) Create a titled group box. Children stack vertically inside the bordered frame. The title string may include a '&amp;' prefix for an accelerator key.</pre>
<h3>API Struct (wgtRegisterApi &quot;box&quot;)</h3>
<pre> Slot Function
---- --------
vBox wgtVBox
hBox wgtHBox
frame wgtFrame</pre>
<p>The designer also registers per-type APIs: &quot;vbox&quot;, &quot;hbox&quot;, and &quot;frame&quot; each expose a single create slot.</p>
<h3>Properties</h3>
<p>Box containers use the common WidgetT fields for layout control. There are no widget-specific properties registered with the interface system.</p>
<pre> Field Description
----- -----------
align Main-axis alignment of children. HBox: Start=left, Center=center, End=right. VBox: Start=top, Center=center, End=bottom.
spacing Gap between children (tagged size).
padding Internal padding around children (tagged size).
weight Controls how the box itself stretches within its parent.</pre>
<p>Frame text is managed via the standard wgtSetText() / wgtGetText() interface (the widget has WCLASS_HAS_TEXT). BASIC code can set its title via the generic &quot;Caption&quot; or &quot;Text&quot; property.</p>
<h3>Events</h3>
<p>Containers use the common events only. No widget-specific events or methods are registered.</p>
<h3>Default Event</h3>
<p>&quot;Click&quot; on all three types.</p>
</div>
<div class="topic" id="widget.button">
<h2>Button</h2>
<p>A push button with a text label. Fires onClick when pressed and released. Uses a two-phase press model: the button visually depresses on mouse-down and fires onClick only when the mouse is released while still inside the button bounds -- dragging the mouse off cancels the press. Supports accelerator keys via '&amp;' prefix in the text (e.g. &quot;&amp;OK&quot; underlines 'O' and binds Alt+O).</p>
<p>Disabled buttons use the classic &quot;embossed&quot; rendering (highlight text offset by +1,+1 and shadow text at 0,0) for a chiseled appearance.</p>
<p>Header: widgets/button.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *btn = wgtButton(parent, &quot;&amp;OK&quot;);
btn-&gt;onClick = onOkClicked;</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtButton(parent, text) Create a push button with the given label text. Pass NULL for no text. Text is copied into the widget.</pre>
<h3>API Struct (wgtRegisterApi &quot;button&quot;)</h3>
<pre> Slot Function
---- --------
create wgtButton</pre>
<h3>Properties</h3>
<p>Uses common WidgetT properties. Label text is managed via wgtSetText() / wgtGetText(). Set accelKey for keyboard shortcut (automatically parsed from '&amp;' prefix in the text). The button is focusable (WCLASS_FOCUSABLE) and draws a focus rectangle when it holds keyboard focus.</p>
<p>No widget-specific properties are registered with the interface system. BASIC code sets the label via the generic &quot;Caption&quot; or &quot;Text&quot; property.</p>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires when the button is clicked (mouse press and release inside, or Space/Enter when focused).</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: CommandButton, namePrefix: Command).</p>
</div>
<div class="topic" id="widget.canvas">
<h2>Canvas</h2>
<p>A freeform drawing surface with a fixed-size pixel buffer stored in the display's native pixel format. Provides drawing primitives (lines, rectangles, circles, text, individual pixels) and supports save/load to image files (BMP/PNG/etc. via dvxLoadImage/dvxSaveImage). Mouse interaction is available via a callback. The buffer is rendered to screen as a straight blit with no per-pixel conversion.</p>
<p>Canvas coordinates are independent of widget position: (0,0) is the top-left of the canvas content, not the widget. The widget frames the buffer with a 2-pixel sunken bevel.</p>
<p>Header: widgets/canvas.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *cv = wgtCanvas(parent, 320, 200);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtCanvas(parent, w, h) Create a canvas with the given pixel dimensions. Buffer is initialized to white.
void wgtCanvasClear(w, color) Fill the entire canvas with a packed color.
void wgtCanvasSetPenColor(w, color) Set the drawing pen color (packed display color).
void wgtCanvasSetPenSize(w, size) Set the drawing pen size in pixels (affects DrawLine dot thickness).
void wgtCanvasDrawLine(w, x0, y0, x1, y1) Draw a line using Bresenham's algorithm with the current pen color and size.
void wgtCanvasDrawRect(w, x, y, width, height) Draw a 1-pixel rectangle outline using the current pen color.
void wgtCanvasFillRect(w, x, y, width, height) Fill a rectangle using the current pen color.
void wgtCanvasFillCircle(w, cx, cy, radius) Fill a circle using the current pen color (integer sqrt; no FPU needed).
void wgtCanvasSetPixel(w, x, y, color) Set a single pixel to the given packed color.
uint32_t wgtCanvasGetPixel(w, x, y) Read a single pixel. Returns packed color.
void wgtCanvasDrawText(w, x, y, text) Draw text at the given canvas coordinates using the current pen color.
void wgtCanvasSetMouseCallback(w, cb) Set a mouse callback. Signature: void (*cb)(WidgetT *w, int32_t cx, int32_t cy, bool drag). cx/cy are canvas-relative, drag=true on mouse-move during press.
int32_t wgtCanvasSave(w, path) Save the canvas buffer to an image file. Returns 0 on success, -1 on error.
int32_t wgtCanvasLoad(w, path) Load an image file into the canvas (resizes buffer to match). Returns 0 on success, -1 on error.
void wgtCanvasResize(w, newW, newH) Resize the canvas buffer. New pixels are filled with white.</pre>
<h3>API Struct (wgtRegisterApi &quot;canvas&quot;)</h3>
<pre> Slot Function
---- --------
create wgtCanvas
clear wgtCanvasClear
setPenColor wgtCanvasSetPenColor
setPenSize wgtCanvasSetPenSize
setMouseCallback wgtCanvasSetMouseCallback
save wgtCanvasSave
load wgtCanvasLoad
drawLine wgtCanvasDrawLine
drawRect wgtCanvasDrawRect
fillRect wgtCanvasFillRect
fillCircle wgtCanvasFillCircle
setPixel wgtCanvasSetPixel
getPixel wgtCanvasGetPixel
drawText wgtCanvasDrawText
resize wgtCanvasResize</pre>
<h3>Properties</h3>
<p>Canvas has no widget-specific properties registered with the interface system. Drawing state (pen color, pen size) is managed by the API functions above.</p>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
Clear color% Fill the entire canvas with a 0x00RRGGBB color.
DrawLine x0%, y0%, x1%, y1%, color% Draw a line between two points.
DrawRect x%, y%, w%, h%, color% Draw a rectangle outline.
DrawText x%, y%, text$ Draw text at the given position.
FillCircle cx%, cy%, radius%, color% Fill a circle.
FillRect x%, y%, w%, h%, color% Fill a rectangle.
GetPixel(x%, y%) Returns the 0x00RRGGBB color at a pixel.
Load path$ Load an image file onto the canvas.
Resize w%, h% Resize the canvas (fills new area with white).
Save path$ Save the canvas to an image file.
SetPenColor color% Set the drawing color (0x00RRGGBB).
SetPenSize size% Set the pen size in pixels.
SetPixel x%, y%, color% Set a single pixel.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires when the canvas is clicked.
Mouse callback (via wgtCanvasSetMouseCallback) Fires on mouse down and drag with canvas-local coordinates.</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: PictureBox, namePrefix: Picture).</p>
</div>
<div class="topic" id="widget.checkbox">
<h2>Checkbox</h2>
<p>A toggle control with a text label. Clicking toggles between checked and unchecked states. Fires onChange each time the state flips. Supports accelerator keys (via '&amp;' in the text) and keyboard toggle via Space or Enter when focused.</p>
<p>The check mark is drawn as an &quot;X&quot; pattern rather than a traditional checkmark glyph. The focus rectangle wraps the label text (not the box), matching the Windows 3.1 convention.</p>
<p>Header: widgets/checkbox.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *cb = wgtCheckbox(parent, &quot;Enable &amp;logging&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtCheckbox(parent, text) Create a checkbox with the given label text.
bool wgtCheckboxIsChecked(w) Returns true if the checkbox is checked.
void wgtCheckboxSetChecked(w, checked) Set the checked state programmatically. Triggers a repaint but does NOT fire onChange.</pre>
<h3>API Struct (wgtRegisterApi &quot;checkbox&quot;)</h3>
<pre> Slot Function
---- --------
create wgtCheckbox
isChecked wgtCheckboxIsChecked
setChecked wgtCheckboxSetChecked</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Value Boolean Read/Write Whether the checkbox is checked.</pre>
<p>Label text is managed via the standard wgtSetText() / wgtGetText() interface. BASIC code uses the generic &quot;Caption&quot; or &quot;Text&quot; property.</p>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires when clicked (after the toggle has already applied).
onChange Fires when the checked state changes (mouse click or keyboard toggle).</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: CheckBox).</p>
</div>
<div class="topic" id="widget.combobox">
<h2>ComboBox</h2>
<p>A combination of a single-line text input and a drop-down list. The user can type a value or select one from the list. When the user picks a list item, its text is copied into the edit buffer. Supports full text editing (cursor movement, selection, clipboard, undo) via the texthelp library, and a popup overlay list via the listhelp library.</p>
<p>Depends on &quot;texthelp&quot; and &quot;listhelp&quot; helper libraries (declared in combobox.dep).</p>
<p>Header: widgets/comboBox.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *cb = wgtComboBox(parent, 128);
wgtComboBoxAddItem(cb, &quot;Arial&quot;);
wgtComboBoxAddItem(cb, &quot;Courier&quot;);
wgtComboBoxAddItem(cb, &quot;Times&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtComboBox(parent, maxLen) Create a combo box. maxLen is the maximum editable text length (0 =&gt; default 256).
void wgtComboBoxSetItems(w, items, count) Set the dropdown items from a const char ** array. Items are not copied -- caller owns them.
int32_t wgtComboBoxGetSelected(w) Get the index of the last selected item (-1 if the text was typed freely).
void wgtComboBoxSetSelected(w, idx) Select an item by index. Copies its text into the edit buffer.
void wgtComboBoxAddItem(w, text) Append an item to the owned list (strdup'd).
void wgtComboBoxRemoveItem(w, idx) Remove an owned item by index.
void wgtComboBoxClear(w) Remove all owned items and reset the selection.
const char *wgtComboBoxGetItem(w, idx) Get the text of an item by index.
int32_t wgtComboBoxGetItemCount(w) Get the total number of items.</pre>
<h3>API Struct (wgtRegisterApi &quot;combobox&quot;)</h3>
<pre> Slot Function
---- --------
create wgtComboBox
setItems wgtComboBoxSetItems
getSelected wgtComboBoxGetSelected
setSelected wgtComboBoxSetSelected
addItem wgtComboBoxAddItem
removeItem wgtComboBoxRemoveItem
clear wgtComboBoxClear
getItem wgtComboBoxGetItem
getItemCount wgtComboBoxGetItemCount</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
ListIndex Integer Read/Write Index of the currently selected item (-1 if none).</pre>
<p>Editable text is accessible via the generic &quot;Text&quot; property. &quot;ListCount&quot; is available through the ListCount method.</p>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
AddItem text$ Append an item to the dropdown list.
Clear Remove all items and clear the selection.
List(index%) Return the text of the item at the given index.
ListCount() Return the total number of items.
RemoveItem index% Remove the item at the given index.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onChange Fires when the selection or text changes.</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: ComboBox).</p>
</div>
<div class="topic" id="widget.datactrl">
<h2>DataCtrl</h2>
<p>A VB3-style Data control for database binding. Displays a visible navigation bar (|&lt; &lt; &gt; &gt;|) that connects to a SQLite database via dvxSql* functions. Reads all rows from the RecordSource query into an in-memory cache for bidirectional navigation. Fires a Reposition event each time the current row changes so bound controls can update. Supports master-detail linking between Data controls (via MasterSource / MasterField / DetailField), INSERT via AddNew, and DELETE via Delete. UPDATEs use the KeyColumn to identify the row.</p>
<p>The widget depends on the &quot;dvxsql&quot; library DXE; the navigation logic caches the full result set so there is no round-trip for MoveNext/MovePrev.</p>
<p>Header: widgets/dataCtrl.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *data = wgtDataCtrl(parent);</code></pre>
<p>Set properties (DatabaseName, RecordSource, KeyColumn, etc.) and then call dataCtrlRefresh to populate.</p>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *dataCtrlCreate(parent) Create a Data control. Exposed as create in the API struct.
void dataCtrlRefresh(w) Re-execute the RecordSource query and rebuild the row cache.
void dataCtrlMoveFirst(w) Move the cursor to the first row.
void dataCtrlMovePrev(w) Move the cursor to the previous row.
void dataCtrlMoveNext(w) Move the cursor to the next row.
void dataCtrlMoveLast(w) Move the cursor to the last row.
const char *dataCtrlGetField(w, colName) Get the value of a column in the current row (case-insensitive).
void dataCtrlSetField(w, colName, value) Set the value of a column in the current row. Marks the row dirty.
void dataCtrlUpdate(w) Flush pending changes (INSERT or UPDATE) to the database.
void dataCtrlUpdateRow(w) Legacy wrapper around dataCtrlUpdate.
void dataCtrlAddNew(w) Append a blank row and move the cursor to it. The row is dirty and new until Update is called.
void dataCtrlDelete(w) Delete the current row from the cache and the database.
void dataCtrlSetMasterValue(w, val) Set the master-detail filter value. Normally managed by the form runtime.
int32_t dataCtrlGetRowCount(w) Get the total number of cached rows.
int32_t dataCtrlGetColCount(w) Get the number of columns in the result set.
const char *dataCtrlGetColName(w, col) Get the name of a column by index.
const char *dataCtrlGetCellText(w, row, col) Get the text of a specific cell.
void dataCtrlSetCurrentRow(w, row) Set the current row by index. Auto-saves the previous row if dirty.</pre>
<h3>API Struct (wgtRegisterApi &quot;data&quot;)</h3>
<pre> Slot Function
---- --------
create dataCtrlCreate
refresh dataCtrlRefresh
moveFirst dataCtrlMoveFirst
movePrev dataCtrlMovePrev
moveNext dataCtrlMoveNext
moveLast dataCtrlMoveLast
getField dataCtrlGetField
setField dataCtrlSetField
updateRow dataCtrlUpdateRow
update dataCtrlUpdate
addNew dataCtrlAddNew
delete dataCtrlDelete
setMasterValue dataCtrlSetMasterValue
getRowCount dataCtrlGetRowCount
getColCount dataCtrlGetColCount
getColName dataCtrlGetColName
getCellText dataCtrlGetCellText
setCurrentRow dataCtrlSetCurrentRow</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
DatabaseName String Read/Write Path to the SQLite database file.
RecordSource String Read/Write SQL query or table name for the result set.
KeyColumn String Read/Write Primary key column name (used for UPDATE/DELETE).
MasterSource String Read/Write Name of the master Data control for master-detail linking.
MasterField String Read/Write Column in the master control to read for the filter value.
DetailField String Read/Write Column in this table to filter by the master value.
Caption String Read/Write Text displayed on the navigator bar.
BOF Boolean Read-only True when the cursor is at the first row (or no rows).
EOF Boolean Read-only True when the cursor is past the last row (or no rows).</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
AddNew Append a blank row and move to it.
Delete Delete the current row.
MoveFirst Move the cursor to the first row.
MoveLast Move the cursor to the last row.
MoveNext Move the cursor to the next row.
MovePrevious Move the cursor to the previous row.
Refresh Re-execute the query and rebuild the cache.
Update Write pending changes to the database.</pre>
<h3>Events</h3>
<pre> Event Description
----- -----------
Reposition Fires when the current row changes. Default event.
Validate Fires before writing. Return false to cancel the write.</pre>
</div>
<div class="topic" id="widget.dbgrid">
<h2>DbGrid</h2>
<p>A database grid widget that displays all records from a Data control in a scrollable, sortable table. Columns auto-populate from the Data control's column names and can be hidden, resized (by dragging a column border), and renamed by the application. Clicking a column header sorts the display ascending/descending. Selecting a row syncs the Data control's cursor position. The grid reads directly from the Data control's cached rows, so there is no separate copy of the data.</p>
<p>The grid supports alternating row shading, vertical and horizontal scrollbars, keyboard navigation (arrows, Page Up/Down, Home, End), and double-click activation (fires onDblClick).</p>
<p>Header: widgets/dbGrid.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *grid = wgtDbGrid(parent);
dbGridSetDataWidget(grid, dataCtrl);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *dbGridCreate(parent) Create a database grid widget. Exposed as create in the API struct.
void dbGridSetDataWidget(w, dataWidget) Bind the grid to a Data control. Auto-populates columns from the Data control's column names.
void dbGridRefresh(w) Re-read the Data control's state and repaint the grid. Rebuilds the sort index if sorting is active.
void dbGridSetColumnVisible(w, fieldName, visible) Show or hide a column by field name.
void dbGridSetColumnHeader(w, fieldName, header) Set a display header for a column (overrides the field name).
void dbGridSetColumnWidth(w, fieldName, width) Set a column's width (tagged size, 0 = auto).
int32_t dbGridGetSelectedRow(w) Get the index of the currently selected data row (-1 if none).</pre>
<h3>API Struct (wgtRegisterApi &quot;dbgrid&quot;)</h3>
<pre> Slot Function
---- --------
create dbGridCreate
setDataWidget dbGridSetDataWidget
refresh dbGridRefresh
setColumnVisible dbGridSetColumnVisible
setColumnHeader dbGridSetColumnHeader
setColumnWidth dbGridSetColumnWidth
getSelectedRow dbGridGetSelectedRow</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
GridLines Boolean Read/Write Whether to draw grid lines between cells (default: true).</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
Refresh Re-read the Data control and repaint.</pre>
<h3>Events</h3>
<pre> Event Description
----- -----------
Click Fires when a row is clicked (selection change).
DblClick Fires when a row is double-clicked. Default event.</pre>
<h3>Default Event</h3>
<p>&quot;DblClick&quot; (VB basName: DBGrid, namePrefix: DBGrid).</p>
</div>
<div class="topic" id="widget.dropdown">
<h2>Dropdown</h2>
<p>A drop-down list that displays a single selected item and expands to a popup list when clicked. Unlike ComboBox, the user cannot type free text -- only list items can be selected. Keyboard navigation: Down/Up to move, Enter to select, type-ahead search on printable keys. The popup overlay is rendered above all other widgets via the widget paint overlay mechanism.</p>
<p>Depends on the &quot;listhelp&quot; helper library (declared in dropdown.dep).</p>
<p>Header: widgets/dropdown.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *dd = wgtDropdown(parent);
wgtDropdownAddItem(dd, &quot;Red&quot;);
wgtDropdownAddItem(dd, &quot;Green&quot;);
wgtDropdownAddItem(dd, &quot;Blue&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtDropdown(parent) Create a dropdown list.
void wgtDropdownSetItems(w, items, count) Set the list from a caller-owned const char ** array.
int32_t wgtDropdownGetSelected(w) Get the index of the selected item (-1 if none).
void wgtDropdownSetSelected(w, idx) Set the selected item by index.
void wgtDropdownAddItem(w, text) Append an owned item (strdup'd).
void wgtDropdownRemoveItem(w, idx) Remove an owned item by index.
void wgtDropdownClear(w) Remove all owned items.
const char *wgtDropdownGetItem(w, idx) Get the text of an item by index.
int32_t wgtDropdownGetItemCount(w) Get the total number of items.</pre>
<h3>API Struct (wgtRegisterApi &quot;dropdown&quot;)</h3>
<pre> Slot Function
---- --------
create wgtDropdown
setItems wgtDropdownSetItems
getSelected wgtDropdownGetSelected
setSelected wgtDropdownSetSelected
addItem wgtDropdownAddItem
removeItem wgtDropdownRemoveItem
clear wgtDropdownClear
getItem wgtDropdownGetItem
getItemCount wgtDropdownGetItemCount</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
ListIndex Integer Read/Write Index of the currently selected item (-1 if none).</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
AddItem text$ Append an item to the drop-down list.
Clear Remove all items.
List(index%) Return the text of the item at the given index.
ListCount() Return the total number of items.
RemoveItem index% Remove the item at the given index.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onChange Fires when the selected item changes.</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: DropDown).</p>
</div>
<div class="topic" id="widget.imagebutton">
<h2>ImageButton</h2>
<p>A clickable button that displays an image instead of text. Has the same press/release visual feedback and focus handling as a regular Button. Can be created from raw pixel data or loaded from an image file. Typically used to populate a Toolbar.</p>
<p>Header: widgets/imgBtn.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *btn = wgtImageButtonFromFile(parent, &quot;icons/save.bmp&quot;);
btn-&gt;onClick = onSaveClicked;</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtImageButton(parent, data, w, h, pitch) Create from raw pixel data (in display's native format).
WidgetT *wgtImageButtonFromFile(parent, path) Create by loading an image file.
void wgtImageButtonSetData(w, data, imgW, imgH, pitch) Replace the image with new raw pixel data.
void wgtImageButtonLoadFile(w, path) Replace the image by loading a new file.</pre>
<h3>API Struct (wgtRegisterApi &quot;imagebutton&quot;)</h3>
<pre> Slot Function
---- --------
create wgtImageButton
fromFile wgtImageButtonFromFile
setData wgtImageButtonSetData
loadFile wgtImageButtonLoadFile</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Picture String Read/Write Setting writes a file path (loads image). Reading returns the current path.
ImageWidth Integer Read-only Width of the currently loaded image in pixels.
ImageHeight Integer Read-only Height of the currently loaded image in pixels.</pre>
<h3>Methods</h3>
<p>No widget-specific BASIC methods. Setting Picture loads a new image.</p>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires when the image button is clicked (press and release inside).</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: ImageButton).</p>
</div>
<div class="topic" id="widget.image">
<h2>Image</h2>
<p>Displays a bitmap image. Can be created from raw pixel data or loaded from a file on disk (BMP/PNG/etc. via dvxLoadImage). Supports optional stretching to fill the widget and transparent color keys for chroma-key style masking.</p>
<p>Header: widgets/image.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *img = wgtImageFromFile(parent, &quot;logo.bmp&quot;);
// or from raw pixels:
// WidgetT *img = wgtImage(parent, pixelData, w, h, pitch);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtImage(parent, data, w, h, pitch) Create from raw pixel data (in display's native format).
WidgetT *wgtImageFromFile(parent, path) Create by loading an image file.
void wgtImageSetData(w, data, imgW, imgH, pitch) Replace the displayed image with new raw pixel data.
void wgtImageLoadFile(w, path) Replace by loading a new file. Static but exposed via the API struct.
void wgtImageSetTransparent(w, hasTransparency, keyColor) Set chroma-key color. Pixels matching keyColor are not drawn.</pre>
<h3>API Struct (wgtRegisterApi &quot;image&quot;)</h3>
<pre> Slot Function
---- --------
create wgtImage
fromFile wgtImageFromFile
setData wgtImageSetData
loadFile wgtImageLoadFile
setTransparent wgtImageSetTransparent</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Picture String Read/Write Setting writes a file path (loads image). Reading returns the current path.
Stretch Boolean Read/Write When true, the image stretches to fill the widget; when false, shown at natural size.
ImageWidth Integer Read-only Width of the currently loaded image in pixels.
ImageHeight Integer Read-only Height of the currently loaded image in pixels.</pre>
<h3>Methods</h3>
<p>No widget-specific BASIC methods. Setting Picture loads a new image.</p>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires when the image is clicked.</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: Image).</p>
</div>
<div class="topic" id="widget.label">
<h2>Label</h2>
<p>A static text label. Does not accept keyboard focus directly, but supports accelerator keys that forward focus to the next focusable sibling (WCLASS_FOCUS_FORWARD). Useful for describing other widgets. Supports left, center, and right text alignment.</p>
<p>Header: widgets/label.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *lbl = wgtLabel(parent, &quot;&amp;Name:&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtLabel(parent, text) Create a text label.
void wgtLabelSetAlign(w, align) Set the text alignment (AlignStartE = left, AlignCenterE = center, AlignEndE = right).
WidgetAlignE wgtLabelGetAlign(w) Get the current text alignment.</pre>
<h3>API Struct (wgtRegisterApi &quot;label&quot;)</h3>
<pre> Slot Function
---- --------
create wgtLabel
setAlign wgtLabelSetAlign</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Alignment Enum (Left, Center, Right) Read/Write Text alignment within the label.</pre>
<p>Label text is managed via the standard wgtSetText() / wgtGetText() interface. BASIC code uses the generic &quot;Caption&quot; or &quot;Text&quot; property. Place an '&amp;' before a character in the caption to mark an accelerator key.</p>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<p>Labels are not focusable, so they typically have no event callbacks. The common onClick callback will fire if the label is clicked.</p>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: Label).</p>
</div>
<div class="topic" id="widget.listbox">
<h2>ListBox</h2>
<p>A scrollable list of text items. Supports single and multi-select modes (Shift-click for range, Ctrl-click to toggle), drag-to-reorder, mouse wheel scroll, and keyboard navigation (Up/Down/PgUp/PgDn/Home/End with type-ahead search on printable keys). Depends on the &quot;listhelp&quot; helper library (declared in listbox.dep).</p>
<p>Items can either be set from a caller-owned array (wgtListBoxSetItems) or managed internally via AddItem/RemoveItem/Clear. The two modes are mutually exclusive per widget.</p>
<p>Header: widgets/listBox.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *lb = wgtListBox(parent);
wgtListBoxAddItem(lb, &quot;Alpha&quot;);
wgtListBoxAddItem(lb, &quot;Beta&quot;);
wgtListBoxAddItem(lb, &quot;Gamma&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtListBox(parent) Create a list box.
void wgtListBoxSetItems(w, items, count) Set items from a caller-owned const char ** array.
int32_t wgtListBoxGetSelected(w) Get the primary selected index (-1 if none).
void wgtListBoxSetSelected(w, idx) Set the selected index. Scrolls the item into view.
void wgtListBoxSetMultiSelect(w, multi) Enable or disable multi-select mode.
bool wgtListBoxIsItemSelected(w, idx) Returns true if the item is selected (multi-select mode).
void wgtListBoxSetItemSelected(w, idx, selected) Select or deselect a specific item (multi-select mode).
void wgtListBoxSelectAll(w) Select every item (multi-select mode).
void wgtListBoxClearSelection(w) Deselect all items.
void wgtListBoxSetReorderable(w, r) Enable drag-to-reorder of items.
void wgtListBoxAddItem(w, text) Append an owned item (strdup'd).
void wgtListBoxRemoveItem(w, idx) Remove an owned item by index.
void wgtListBoxClear(w) Remove all owned items.
const char *wgtListBoxGetItem(w, idx) Get the text of an item by index.
int32_t wgtListBoxGetItemCount(w) Get the total number of items.</pre>
<h3>API Struct (wgtRegisterApi &quot;listbox&quot;)</h3>
<pre> Slot Function
---- --------
create wgtListBox
setItems wgtListBoxSetItems
getSelected wgtListBoxGetSelected
setSelected wgtListBoxSetSelected
setMultiSelect wgtListBoxSetMultiSelect
isItemSelected wgtListBoxIsItemSelected
setItemSelected wgtListBoxSetItemSelected
selectAll wgtListBoxSelectAll
clearSelection wgtListBoxClearSelection
setReorderable wgtListBoxSetReorderable
addItem wgtListBoxAddItem
removeItem wgtListBoxRemoveItem
clear wgtListBoxClear
getItem wgtListBoxGetItem
getItemCount wgtListBoxGetItemCount</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
ListIndex Integer Read/Write Index of the currently selected item.</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
AddItem text$ Append an item.
Clear Remove all items.
ClearSelection Deselect all items.
IsItemSelected(index%) Returns True if the item is selected (multi-select mode).
List(index%) Return the text of the item at the given index.
ListCount() Return the total number of items.
RemoveItem index% Remove the item at the given index.
SelectAll Select all items.
SetItemSelected index%, sel Select or deselect a specific item.
SetItems spec$ Bulk-load items from a pipe-delimited string (e.g. &quot;Red|Green|Blue&quot;); replaces existing items.
SetMultiSelect multi Enable or disable multi-select mode.
SetReorderable r Enable or disable drag-to-reorder.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires when an item is clicked.
onDblClick Fires when an item is double-clicked.
onChange Fires when the selection changes.</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: ListBox).</p>
</div>
<div class="topic" id="widget.listview">
<h2>ListView</h2>
<p>A multi-column list with sortable headers. Supports single and multi-selection, column alignment, header click sorting, and drag-to-reorder. Data is provided as a flat array of strings (row-major order, one string per cell).</p>
<p>Header: widgets/listView.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *lv = wgtListView(parent);
ListViewColT cols[] = {
{ &quot;Name&quot;, wgtChars(20), ListViewAlignLeftE },
{ &quot;Size&quot;, wgtChars(10), ListViewAlignRightE }
};
wgtListViewSetColumns(lv, cols, 2);
const char *cells[] = { &quot;file.txt&quot;, &quot;1234&quot;, &quot;readme.md&quot;, &quot;5678&quot; };
wgtListViewSetData(lv, cells, 2);</code></pre>
<h3>Column Definition</h3>
<pre><code>typedef struct {
const char *title;
int32_t width; // tagged size (wgtPixels/wgtChars/wgtPercent, 0 = auto)
ListViewAlignE align; // ListViewAlignLeftE, ListViewAlignCenterE, ListViewAlignRightE
} ListViewColT;</code></pre>
<h3>Sort Direction</h3>
<pre><code>typedef enum {
ListViewSortNoneE,
ListViewSortAscE,
ListViewSortDescE
} ListViewSortE;</code></pre>
<h3>Macros</h3>
<pre> Macro Description
----- -----------
wgtListView(parent) Create a list view.
wgtListViewSetColumns(w, cols, count) Define columns from an array of ListViewColT.
wgtListViewSetData(w, cellData, rowCount) Set row data. cellData is a flat const char ** array of size rowCount * colCount.
wgtListViewGetSelected(w) Get the index of the selected row (-1 if none).
wgtListViewSetSelected(w, idx) Set the selected row by index.
wgtListViewSetSort(w, col, dir) Set the sort column and direction.
wgtListViewSetHeaderClickCallback(w, cb) Set a callback for header clicks. Signature: void (*cb)(WidgetT *w, int32_t col, ListViewSortE dir).
wgtListViewSetMultiSelect(w, multi) Enable or disable multi-selection.
wgtListViewIsItemSelected(w, idx) Check if a specific row is selected.
wgtListViewSetItemSelected(w, idx, selected) Select or deselect a specific row.
wgtListViewSelectAll(w) Select all rows.
wgtListViewClearSelection(w) Deselect all rows.
wgtListViewSetReorderable(w, reorderable) Enable drag-to-reorder of rows.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires when a row is clicked.
onDblClick Fires when a row is double-clicked.
onChange Fires when the selection changes.</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
ListIndex Integer Read/Write Index of the currently selected row.</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
AddItem text$ Add a row (sets first column text).
Clear Remove all rows.
ClearSelection Deselect all rows.
GetCell(row%, col%) Returns the text of a cell.
IsItemSelected(index%) Check if a specific row is selected.
RemoveItem index% Remove a row by index.
RowCount() Returns the number of rows.
SelectAll Select all rows.
SetCell row%, col%, text$ Set the text of a cell.
SetColumns spec$ Define columns from a pipe-delimited spec string (&quot;Name,Width|Name,Width&quot;).
SetItemSelected idx%, sel Select or deselect a specific row by index.
SetMultiSelect multi Enable or disable multi-selection.
SetReorderable reorderable Enable or disable drag-to-reorder.
SetSort col%, dir% Set the sort column and direction (0=none, 1=ascending, 2=descending).</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: ListView).</p>
</div>
<div class="topic" id="widget.progressbar">
<h2>ProgressBar</h2>
<p>A visual indicator of progress, displayed as a filled bar. Supports both horizontal and vertical orientations. Value ranges from 0 to 100.</p>
<p>Header: widgets/progress.h</p>
<h3>Creation</h3>
<pre> Macro Description
----- -----------
wgtProgressBar(parent) Create a horizontal progress bar.
wgtProgressBarV(parent) Create a vertical progress bar.</pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtProgressBar(parent) Create a horizontal progress bar.
WidgetT *wgtProgressBarV(parent) Create a vertical progress bar.
void wgtProgressBarSetValue(w, val) Set the progress value (0-100). Clamped to 0..maxValue.
int32_t wgtProgressBarGetValue(w) Get the current progress value.</pre>
<h3>API Struct (wgtRegisterApi &quot;progressbar&quot;)</h3>
<pre> Slot Function
---- --------
create wgtProgressBar
createV wgtProgressBarV
setValue wgtProgressBarSetValue
getValue wgtProgressBarGetValue</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Value Integer Read/Write Current progress value (0-100).</pre>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<p>ProgressBar is a display-only widget. Typically no callbacks are set.</p>
<h3>Default Event</h3>
<p>None. (VB basName: ProgressBar.)</p>
</div>
<div class="topic" id="widget.radio">
<h2>Radio Button</h2>
<p>A mutually exclusive selection control. Radio buttons must be placed inside a radio group container. Only one radio button within a group can be selected at a time.</p>
<p>Header: widgets/radio.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *grp = wgtRadioGroup(parent);
WidgetT *r1 = wgtRadio(grp, &quot;Option A&quot;);
WidgetT *r2 = wgtRadio(grp, &quot;Option B&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtRadioGroup(parent) Create a radio group container.
WidgetT *wgtRadio(parent, text) Create a radio button inside a group.
void wgtRadioGroupSetSelected(group, idx) Set the selected radio button by index within the group.
int32_t wgtRadioGetIndex(w) Get the index of this radio button within its group.</pre>
<h3>API Struct (wgtRegisterApi &quot;radio&quot;)</h3>
<pre> Slot Function
---- --------
group wgtRadioGroup
create wgtRadio
groupSetSelected wgtRadioGroupSetSelected
getIndex wgtRadioGetIndex</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Value Integer Read-only Index of this radio button within its group.</pre>
<p>Caption is managed via the standard wgtSetText() / wgtGetText() interface (WCLASS_HAS_TEXT).</p>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
SetSelected idx% Set the selected radio button by index within the group.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires on the radio button when clicked.
onChange Fires when the selection changes.</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: OptionButton, namePrefix: Option).</p>
</div>
<div class="topic" id="widget.scrollpane">
<h2>ScrollPane</h2>
<p>A scrollable container that provides vertical and/or horizontal scrollbars when its content exceeds the visible area. Place a single child (typically a VBox or HBox) inside the scroll pane.</p>
<p>Header: widgets/scrlPane.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *sp = wgtScrollPane(parent);
WidgetT *content = wgtVBox(sp);
// add children to content...</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtScrollPane(parent) Create a scroll pane container.
void wgtScrollPaneScrollToChild(sp, child) Scroll so that the given child widget is visible.
void wgtScrollPaneScrollToTop(w) Scroll back to the top-left of the content.
void wgtScrollPaneSetNoBorder(w, noBorder) When true, removes the border around the scroll pane.</pre>
<h3>API Struct (wgtRegisterApi &quot;scrollpane&quot;)</h3>
<pre> Slot Function
---- --------
create wgtScrollPane
scrollToChild wgtScrollPaneScrollToChild
setNoBorder wgtScrollPaneSetNoBorder
scrollToTop wgtScrollPaneScrollToTop</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
NoBorder Boolean Read/Write Whether the border around the scroll pane is hidden.</pre>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onScroll Fires when the scroll position changes.</pre>
<h3>Default Event</h3>
<p>None. (VB basName: ScrollPane, namePrefix: Scroll.)</p>
</div>
<div class="topic" id="widget.separator">
<h2>Separator</h2>
<p>A visual dividing line used to separate groups of widgets. Available in horizontal and vertical orientations.</p>
<p>Header: widgets/separatr.h</p>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtHSeparator(parent) Create a horizontal separator line.
WidgetT *wgtVSeparator(parent) Create a vertical separator line.</pre>
<h3>API Struct (wgtRegisterApi &quot;separator&quot;)</h3>
<pre> Slot Function
---- --------
hSeparator wgtHSeparator
vSeparator wgtVSeparator</pre>
<h3>Properties</h3>
<p>No widget-specific properties.</p>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<p>Separator is a visual-only widget. No events.</p>
<h3>Default Event</h3>
<p>None. (VB basName: Line.)</p>
</div>
<div class="topic" id="widget.slider">
<h2>Slider</h2>
<p>A horizontal slider (track bar) for selecting an integer value within a range. The user drags the thumb or clicks the track to change the value.</p>
<p>Header: widgets/slider.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *sl = wgtSlider(parent, 0, 100);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtSlider(parent, minVal, maxVal) Create a slider with the given integer range.
void wgtSliderSetValue(w, value) Set the slider value programmatically.
int32_t wgtSliderGetValue(w) Get the current slider value.</pre>
<h3>API Struct (wgtRegisterApi &quot;slider&quot;)</h3>
<pre> Slot Function
---- --------
create wgtSlider
setValue wgtSliderSetValue
getValue wgtSliderGetValue</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Value Integer Read/Write Current slider value.</pre>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onChange Fires when the slider value changes.</pre>
<h3>Default Event</h3>
<p>&quot;Change&quot; (VB basName: HScrollBar, namePrefix: HScroll).</p>
</div>
<div class="topic" id="widget.spacer">
<h2>Spacer</h2>
<p>An invisible widget used for layout purposes. By default it has weight=100, so it absorbs available extra space. Useful for pushing other widgets apart or aligning them to edges.</p>
<p>Header: widgets/spacer.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *row = wgtHBox(parent);
wgtButton(row, &quot;OK&quot;);
wgtSpacer(row); // pushes Cancel to the right
wgtButton(row, &quot;Cancel&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtSpacer(parent) Create an invisible spacer widget.</pre>
<h3>API Struct (wgtRegisterApi &quot;spacer&quot;)</h3>
<pre> Slot Function
---- --------
create wgtSpacer</pre>
<h3>Properties, Methods, Events</h3>
<p>Spacer is an invisible layout widget. No type-specific properties, methods, or events.</p>
<h3>Default Event</h3>
<p>None. (VB basName: Spacer.)</p>
</div>
<div class="topic" id="widget.spinner">
<h2>Spinner</h2>
<p>A numeric input with up/down buttons for incrementing and decrementing a value within a range. Supports both integer and floating-point (real) modes.</p>
<p>Header: widgets/spinner.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *sp = wgtSpinner(parent, 0, 100, 1);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtSpinner(parent, minVal, maxVal, step) Create a spinner with the given integer range and step size.
void wgtSpinnerSetValue(w, value) Set the integer value.
int32_t wgtSpinnerGetValue(w) Get the current integer value.
void wgtSpinnerSetRange(w, minVal, maxVal) Set the integer range.
void wgtSpinnerSetStep(w, step) Set the integer step size.
void wgtSpinnerSetRealMode(w, enable) Switch to floating-point mode.
double wgtSpinnerGetRealValue(w) Get the current floating-point value.
void wgtSpinnerSetRealValue(w, value) Set the floating-point value.
void wgtSpinnerSetRealRange(w, minVal, maxVal) Set the floating-point range.
void wgtSpinnerSetRealStep(w, step) Set the floating-point step size.
void wgtSpinnerSetDecimals(w, decimals) Set the number of decimal places displayed in real mode.</pre>
<h3>API Struct (wgtRegisterApi &quot;spinner&quot;)</h3>
<pre> Slot Function
---- --------
create wgtSpinner
setValue wgtSpinnerSetValue
getValue wgtSpinnerGetValue
setRange wgtSpinnerSetRange
setStep wgtSpinnerSetStep
setRealMode wgtSpinnerSetRealMode
getRealValue wgtSpinnerGetRealValue
setRealValue wgtSpinnerSetRealValue
setRealRange wgtSpinnerSetRealRange
setRealStep wgtSpinnerSetRealStep
setDecimals wgtSpinnerSetDecimals</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Value Integer Read/Write Current integer value.
RealMode Boolean Read/Write Whether floating-point mode is active.
Decimals Integer Read/Write Number of decimal places displayed in real mode.</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
SetRange min%, max% Set the integer range.
SetStep step% Set the integer step size.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onChange Fires when the value changes.</pre>
<h3>Default Event</h3>
<p>&quot;Change&quot; (VB basName: SpinButton, namePrefix: Spin).</p>
</div>
<div class="topic" id="widget.splitter">
<h2>Splitter</h2>
<p>A two-pane container with a draggable divider. The user drags the splitter bar to resize the two panes. Can be oriented vertically (left/right panes) or horizontally (top/bottom panes). Add exactly two children.</p>
<p>Header: widgets/splitter.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *sp = wgtSplitter(parent, true); // vertical = left|right
WidgetT *left = wgtVBox(sp);
WidgetT *right = wgtVBox(sp);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtSplitter(parent, vertical) Create a splitter. vertical=true for left/right panes (vertical divider), false for top/bottom.
void wgtSplitterSetPos(w, pos) Set the divider position in pixels from the leading edge.
int32_t wgtSplitterGetPos(w) Get the current divider position in pixels.</pre>
<h3>API Struct (wgtRegisterApi &quot;splitter&quot;)</h3>
<pre> Slot Function
---- --------
create wgtSplitter
setPos wgtSplitterSetPos
getPos wgtSplitterGetPos</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Position Integer Read/Write Divider position in pixels.</pre>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<p>Splitter has no widget-specific events. Common events apply.</p>
<h3>Default Event</h3>
<p>None. (VB basName: Splitter.)</p>
</div>
<div class="topic" id="widget.statusbar">
<h2>StatusBar</h2>
<p>A horizontal bar typically placed at the bottom of a window for displaying status text and informational widgets. Children are laid out horizontally.</p>
<p>Header: widgets/statBar.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *sb = wgtStatusBar(parent);
wgtLabel(sb, &quot;Ready&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtStatusBar(parent) Create a status bar container.</pre>
<h3>API Struct (wgtRegisterApi &quot;statusbar&quot;)</h3>
<pre> Slot Function
---- --------
create wgtStatusBar</pre>
<h3>Properties, Methods, Events</h3>
<p>StatusBar has no widget-specific properties, methods, or events. Add child widgets (labels, progress bars, etc.) to populate.</p>
<h3>Default Event</h3>
<p>None. (VB basName: StatusBar.)</p>
</div>
<div class="topic" id="widget.tabcontrol">
<h2>TabControl</h2>
<p>A tabbed container that displays one page at a time with clickable tabs along the top. Each tab page is a container that holds its own child widgets.</p>
<p>Header: widgets/tabCtrl.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *tabs = wgtTabControl(parent);
WidgetT *page1 = wgtTabPage(tabs, &quot;General&quot;);
WidgetT *page2 = wgtTabPage(tabs, &quot;Advanced&quot;);
// add children to page1, page2...</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtTabControl(parent) Create a tab control.
WidgetT *wgtTabPage(parent, title) Add a tab page with the given title. Returns the page container widget.
void wgtTabControlSetActive(w, idx) Set the active tab by index (0-based).
int32_t wgtTabControlGetActive(w) Get the index of the active tab.</pre>
<h3>API Struct (wgtRegisterApi &quot;tabcontrol&quot;)</h3>
<pre> Slot Function
---- --------
create wgtTabControl
page wgtTabPage
setActive wgtTabControlSetActive
getActive wgtTabControlGetActive</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
TabIndex Integer Read/Write Index of the currently active tab (0-based).</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
AddPage title$ Add a new tab page with the given title.
GetActive() Returns the index of the active tab.
SetActive idx% Set the active tab by index (0-based).</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onChange Fires when the active tab changes.</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: TabStrip).</p>
</div>
<div class="topic" id="widget.textinput">
<h2>TextInput / TextArea</h2>
<p>Single-line text input, password input, masked input, and multi-line text area with optional syntax colorization, line numbers, find/replace, and gutter decorators.</p>
<p>Header: widgets/textInpt.h</p>
<h3>Creation</h3>
<pre> Macro Description
----- -----------
wgtTextInput(parent, maxLen) Create a single-line text input. maxLen is the maximum number of characters.
wgtPasswordInput(parent, maxLen) Create a password input (characters displayed as bullets).
wgtMaskedInput(parent, mask) Create a masked input field. The mask string defines the input format.
wgtTextArea(parent, maxLen) Create a multi-line text area.</pre>
<h3>API Functions (TextArea-specific)</h3>
<pre> Function Description
-------- -----------
void wgtTextAreaAppendText(w, text) Append text to the end of the buffer and invalidate the widget.
void wgtTextAreaSetColorize(w, fn, ctx) Set a syntax colorization callback. The callback receives each line and fills a color index array.
void wgtTextAreaGoToLine(w, line) Scroll to and place the cursor on the given line number.
void wgtTextAreaSetAutoIndent(w, enable) Enable or disable automatic indentation on newline.
void wgtTextAreaSetShowLineNumbers(w, show) Show or hide line numbers in the gutter.
void wgtTextAreaSetCaptureTabs(w, capture) When true, Tab key inserts a tab/spaces instead of moving focus.
void wgtTextAreaSetTabWidth(w, width) Set the tab stop width in characters.
void wgtTextAreaSetUseTabChar(w, useChar) When true, insert literal tab characters; when false, insert spaces.
bool wgtTextAreaFindNext(w, needle, caseSens, fwd) Search for the next occurrence. Returns true if found.
int32_t wgtTextAreaReplaceAll(w, needle, repl, caseSens) Replace all occurrences. Returns the number of replacements made.
void wgtTextAreaSetLineDecorator(w, fn, ctx) Set a gutter line decorator callback. Returns a color and receives the line number.
int32_t wgtTextAreaGetCursorLine(w) Get the current cursor line number.
void wgtTextAreaSetGutterClickCallback(w, fn) Set a callback for gutter clicks (e.g. for breakpoint toggling).
int32_t wgtTextAreaGetWordAtCursor(w, buf, bufSize) Copy the word under the cursor into buf. Returns its length.
void wgtTextAreaSetSyntaxColors(w, colors, count) Set the color palette used by the colorizer.</pre>
<h3>API Struct (wgtRegisterApi &quot;textinput&quot;)</h3>
<p>The combined &quot;textinput&quot; API exposes all four constructors plus the TextArea functions. The designer uses per-type APIs registered under the names &quot;textbox&quot; (single-line) and &quot;textarea&quot; (multi-line), each exposing only a create slot.</p>
<h3>Properties (BASIC Interface)</h3>
<p>TextBox has no widget-specific properties. Text is managed via the generic &quot;Text&quot; property. TextArea exposes:</p>
<pre> Property Type Access Description
-------- ---- ------ -----------
CursorLine Integer Read-only Current cursor line number (0-based).</pre>
<h3>Methods (BASIC Interface, TextArea)</h3>
<pre> Method Description
------ -----------
FindNext needle$, caseSensitive, forward Search for the next occurrence. Returns True if found.
GetWordAtCursor() Returns the word under the cursor.
GoToLine line% Scroll to and position the cursor on a line.
ReplaceAll needle$, replacement$, caseSensitive Replace all occurrences. Returns the count.
SetAutoIndent enabled Enable or disable automatic indentation on newline.
SetCaptureTabs enabled When True, Tab inserts whitespace instead of moving focus.
SetShowLineNumbers show Show or hide line numbers in the gutter.
SetSyntaxMode mode$ Activate built-in syntax highlighting (e.g. &quot;dhs&quot;, &quot;bas&quot;; &quot;&quot; to disable).
SetTabWidth width% Set the tab stop width in characters.
SetUseTabChar useChar When True, Tab inserts a literal tab; when False, spaces.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onChange Fires when the text content changes.
onKeyPress Fires on each key press (ASCII value).
onValidate Called before committing a change. Return false to cancel.</pre>
<h3>Default Event</h3>
<p>&quot;Change&quot; for both TextBox (basName: TextBox) and TextArea (basName: TextArea).</p>
</div>
<div class="topic" id="widget.timer">
<h2>Timer</h2>
<p>A non-visual widget that fires its onClick callback at a regular interval. Useful for animations, polling, and periodic updates. Must be explicitly started after creation.</p>
<p>Header: widgets/timer.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *tmr = wgtTimer(parent, 1000, true); // 1 second, repeating
tmr-&gt;onClick = onTimerTick;
wgtTimerStart(tmr);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtTimer(parent, intervalMs, repeat) Create a timer. intervalMs is the interval in milliseconds. repeat: true for repeating, false for one-shot.
void wgtTimerStart(w) Start the timer.
void wgtTimerStop(w) Stop the timer.
void wgtTimerSetInterval(w, intervalMs) Change the timer interval.
int32_t wgtTimerGetInterval(w) Returns the current interval in milliseconds.
bool wgtTimerIsRunning(w) Returns true if the timer is currently running.
void wgtTimerSetEnabled(w, enabled) Start or stop the timer based on enabled flag.
void wgtUpdateTimers(void) Global tick function. Called by the event loop to advance all active timers.</pre>
<h3>API Struct (wgtRegisterApi &quot;timer&quot;)</h3>
<pre> Slot Function
---- --------
create wgtTimer
start wgtTimerStart
stop wgtTimerStop
setInterval wgtTimerSetInterval
isRunning wgtTimerIsRunning
updateTimers wgtUpdateTimers</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires each time the timer elapses (the BASIC layer surfaces this as the &quot;Timer&quot; event).</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Enabled Boolean Read/Write Whether the timer is running. Reading returns the running state; writing starts or stops it.
Interval Integer Read/Write Timer interval in milliseconds.</pre>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
Start Start the timer.
Stop Stop the timer.</pre>
<h3>Extra Events (BASIC Interface)</h3>
<pre> Event Description
----- -----------
Timer Fires each time the timer elapses. Default event.</pre>
<hr>
</div>
<div class="topic" id="widget.toolbar">
<h2>Toolbar</h2>
<p>A horizontal container for toolbar buttons and controls. Typically placed at the top of a window. Children (usually ImageButtons or Buttons) are laid out horizontally with toolbar-appropriate spacing.</p>
<p>Header: widgets/toolbar.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *tb = wgtToolbar(parent);
wgtImageButtonFromFile(tb, &quot;icons/save.bmp&quot;);
wgtImageButtonFromFile(tb, &quot;icons/open.bmp&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtToolbar(parent) Create a toolbar container.</pre>
<h3>API Struct (wgtRegisterApi &quot;toolbar&quot;)</h3>
<pre> Slot Function
---- --------
create wgtToolbar</pre>
<h3>Properties, Methods, Events</h3>
<p>Toolbar has no widget-specific properties, methods, or events. Add children (buttons, separators, etc.) to populate.</p>
<h3>Default Event</h3>
<p>None. (VB basName: Toolbar.)</p>
</div>
<div class="topic" id="widget.treeview">
<h2>TreeView</h2>
<p>A hierarchical tree control with expandable/collapsible nodes. Supports single and multi-selection and drag-to-reorder. Tree items are added as children of the TreeView or of other tree items to create nested hierarchies.</p>
<p>Header: widgets/treeView.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *tv = wgtTreeView(parent);
WidgetT *root = wgtTreeItem(tv, &quot;Root&quot;);
WidgetT *child = wgtTreeItem(root, &quot;Child&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
WidgetT *wgtTreeView(parent) Create a tree view control.
WidgetT *wgtTreeItem(parent, text) Add a tree item as a child of the tree view or another tree item.
WidgetT *wgtTreeViewGetSelected(w) Get the currently selected tree item (NULL if none).
void wgtTreeViewSetSelected(w, item) Set the selected tree item.
void wgtTreeViewSetMultiSelect(w, multi) Enable or disable multi-selection.
void wgtTreeViewSetReorderable(w, reorderable) Enable drag-to-reorder of items.
void wgtTreeItemSetExpanded(w, expanded) Expand or collapse a tree item.
bool wgtTreeItemIsExpanded(w) Check if a tree item is expanded.
bool wgtTreeItemIsSelected(w) Check if a tree item is selected (multi-select mode).
void wgtTreeItemSetSelected(w, selected) Select or deselect a tree item.</pre>
<h3>API Struct (wgtRegisterApi &quot;treeview&quot;)</h3>
<pre> Slot Function
---- --------
create wgtTreeView
getSelected wgtTreeViewGetSelected
setSelected wgtTreeViewSetSelected
setMultiSelect wgtTreeViewSetMultiSelect
setReorderable wgtTreeViewSetReorderable
item wgtTreeItem
itemSetExpanded wgtTreeItemSetExpanded
itemIsExpanded wgtTreeItemIsExpanded
itemIsSelected wgtTreeItemIsSelected
itemSetSelected wgtTreeItemSetSelected</pre>
<h3>Properties</h3>
<p>No widget-specific properties.</p>
<h3>Methods (BASIC Interface)</h3>
<pre> Method Description
------ -----------
AddChildItem parentIdx%, text$ Add a child node under the node at the given index.
AddItem text$ Add a root-level node.
Clear Remove all nodes.
GetItemText(index%) Returns the text of the node at the given depth-first index.
IsExpanded(index%) Returns True if the node is expanded.
IsItemSelected(index%) Returns True if the node is selected.
ItemCount() Returns the total number of nodes.
SetExpanded index%, expanded Expand or collapse the node.
SetItemSelected index%, selected Select or deselect the node.
SetMultiSelect multi Enable or disable multi-selection.
SetReorderable reorderable Enable or disable drag-to-reorder.</pre>
<h3>Events</h3>
<pre> Callback Description
-------- -----------
onClick Fires when a tree item is clicked.
onDblClick Fires when a tree item is double-clicked.
onChange Fires when the selection changes.</pre>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: TreeView).</p>
</div>
<div class="topic" id="widget.wrapbox">
<h2>WrapBox</h2>
<p>A flow/wrap layout container that arranges children left-to-right, wrapping to the next row when the available width is exceeded. Each row's height is the maximum child height in that row. Supports configurable spacing between items and rows, and per-row alignment for short rows.</p>
<p>Header: widgets/wrapBox.h</p>
<h3>Creation</h3>
<pre><code>WidgetT *wrap = wgtWrapBox(parent);
wgtButton(wrap, &quot;Tag 1&quot;);
wgtButton(wrap, &quot;Tag 2&quot;);
wgtButton(wrap, &quot;Tag 3&quot;);</code></pre>
<h3>API Functions</h3>
<pre> Function Description
-------- -----------
wgtWrapBox(parent) Create a wrap box container. Macro that calls the registered &quot;wrapbox&quot; create slot.</pre>
<h3>API Struct (wgtRegisterApi &quot;wrapbox&quot;)</h3>
<pre> Slot Function
---- --------
create wrapBoxCreate</pre>
<h3>Properties (Common Container Fields)</h3>
<p>WrapBox uses the common WidgetT container fields for layout control:</p>
<pre> Property Description
-------- -----------
spacing Gap between children in both the horizontal and vertical directions (tagged size). Default is 4 pixels.
padding Internal padding around children (tagged size). Default is 2 pixels.</pre>
<h3>Properties (BASIC Interface)</h3>
<pre> Property Type Access Description
-------- ---- ------ -----------
Alignment Enum (Left, Center, Right) Read/Write Row alignment for rows that do not fill the full width.</pre>
<h3>Methods</h3>
<p>No widget-specific methods.</p>
<h3>Events</h3>
<p>WrapBox is a container widget. It uses the common events only. No widget-specific events are defined.</p>
<h3>Default Event</h3>
<p>&quot;Click&quot; (VB basName: WrapBox, namePrefix: WrapBox).</p>
</div>
</main>
</body>
</html>