1117 lines
39 KiB
Markdown
1117 lines
39 KiB
Markdown
# DV/X GUI
|
|
|
|
A DESQview/X-style windowed GUI compositor for DOS, targeting DJGPP/DPMI with
|
|
VESA VBE 2.0+ linear framebuffer.
|
|
|
|
Motif-style beveled chrome, dirty-rectangle compositing, draggable and
|
|
resizable windows, dropdown menus, scrollbars, and a declarative widget/layout
|
|
system with buttons, checkboxes, radios, text inputs, dropdowns, combo boxes,
|
|
sliders, spinners, progress bars, tab controls, tree views, list views,
|
|
scroll panes, toolbars, status bars, images, image buttons, drawable canvases,
|
|
password inputs, masked/formatted inputs, and an ANSI BBS terminal emulator.
|
|
|
|
## Building
|
|
|
|
Requires the DJGPP cross-compiler (`i586-pc-msdosdjgpp-gcc`).
|
|
|
|
The GUI is built as a static library (`lib/libdvx.a`). The demo links
|
|
against it.
|
|
|
|
```
|
|
cd dvxdemo
|
|
make # builds lib/libdvx.a then bin/demo.exe
|
|
make clean # removes obj/ and bin/
|
|
```
|
|
|
|
Set `DJGPP_PREFIX` in the Makefile if your toolchain is installed somewhere
|
|
other than `~/djgpp/djgpp`.
|
|
|
|
## Architecture
|
|
|
|
The library is organized in five layers. Each layer is a `.h`/`.c` pair.
|
|
Application code only needs to include `dvxApp.h` (which pulls in the rest)
|
|
and optionally `dvxWidget.h`.
|
|
|
|
```
|
|
Layer 1 dvxVideo VESA init, LFB mapping, backbuffer, pixel format
|
|
Layer 2 dvxDraw Spans, rects, bevels, text, bitmaps (asm inner loops)
|
|
Layer 3 dvxComp Dirty rectangle list, merge, LFB flush
|
|
Layer 4 dvxWm Window stack, chrome, drag, resize, focus, menus, scrollbars
|
|
Layer 5 dvxApp Event loop, mouse/keyboard input, public API
|
|
dvxWidget Widget/layout system (optional, standalone)
|
|
```
|
|
|
|
Supporting files:
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `dvxTypes.h` | Shared type definitions used by all layers |
|
|
| `dvxFont.h` | Built-in 8x14 bitmap font glyph data |
|
|
| `dvxCursor.h` | Mouse cursor bitmask data (5 shapes) |
|
|
| `dvxPalette.h` | Default VGA palette for 8-bit mode |
|
|
| `dvxIcon.c` | stb_image implementation unit (BMP/PNG/JPEG/GIF) |
|
|
| `dvxImageWrite.c` | stb_image_write implementation unit (PNG export) |
|
|
| `thirdparty/stb_image.h` | Third-party single-header image loader |
|
|
| `thirdparty/stb_image_write.h` | Third-party single-header image writer |
|
|
|
|
The widget system lives in `widgets/`:
|
|
|
|
| File | Purpose |
|
|
|------|---------|
|
|
| `widgets/widgetInternal.h` | Shared internal header: vtable type, constants, cross-widget prototypes |
|
|
| `widgets/widgetClass.c` | Widget class table: one `WidgetClassT` vtable entry per widget type |
|
|
| `widgets/widgetCore.c` | Allocation, tree ops, hit testing, flag-based type queries |
|
|
| `widgets/widgetLayout.c` | Two-pass layout engine (measure + arrange) |
|
|
| `widgets/widgetEvent.c` | Mouse, keyboard, scroll, resize, and paint event dispatch |
|
|
| `widgets/widgetOps.c` | Paint dispatcher, public operations (`wgtFind`, `wgtDestroy`, etc.) |
|
|
| `widgets/widget*.c` | One file per widget type (button, checkbox, slider, etc.) |
|
|
|
|
Each widget type is self-contained in its own `.c` file. Dispatch for
|
|
paint, layout, mouse, keyboard, getText/setText, and destroy is driven
|
|
by a per-type vtable (`WidgetClassT`) rather than switch statements in
|
|
the core files. Adding a new widget type requires only a new `.c` file
|
|
and an entry in the class table.
|
|
|
|
## Quick start
|
|
|
|
```c
|
|
#include "dvxApp.h"
|
|
|
|
static void onPaint(WindowT *win, RectT *dirty) {
|
|
AppContextT *ctx = (AppContextT *)win->userData;
|
|
const BlitOpsT *ops = dvxGetBlitOps(ctx);
|
|
const DisplayT *d = dvxGetDisplay(ctx);
|
|
uint32_t blue = packColor(d, 0, 0, 200);
|
|
|
|
for (int32_t y = 0; y < win->contentH; y++) {
|
|
ops->spanFill(win->contentBuf + y * win->contentPitch,
|
|
blue, win->contentW);
|
|
}
|
|
}
|
|
|
|
int main(void) {
|
|
AppContextT ctx;
|
|
|
|
if (dvxInit(&ctx, 1024, 768, 16) != 0) {
|
|
return 1;
|
|
}
|
|
|
|
WindowT *win = dvxCreateWindow(&ctx, "Hello", 100, 100, 300, 200, true);
|
|
win->userData = &ctx;
|
|
win->onPaint = onPaint;
|
|
|
|
RectT r = {0, 0, win->contentW, win->contentH};
|
|
win->onPaint(win, &r);
|
|
|
|
dvxRun(&ctx);
|
|
dvxShutdown(&ctx);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
## Quick start (widgets)
|
|
|
|
```c
|
|
#include "dvxApp.h"
|
|
#include "dvxWidget.h"
|
|
|
|
static void onButtonClick(WidgetT *w) {
|
|
WidgetT *root = w;
|
|
while (root->parent) root = root->parent;
|
|
|
|
WidgetT *lbl = wgtFind(root, "status");
|
|
if (lbl) {
|
|
wgtSetText(lbl, "Clicked!");
|
|
wgtInvalidate(lbl);
|
|
}
|
|
}
|
|
|
|
int main(void) {
|
|
AppContextT ctx;
|
|
dvxInit(&ctx, 1024, 768, 16);
|
|
|
|
WindowT *win = dvxCreateWindow(&ctx, "Widgets", 100, 100, 260, 200, true);
|
|
win->userData = &ctx;
|
|
|
|
WidgetT *root = wgtInitWindow(&ctx, win);
|
|
|
|
WidgetT *lbl = wgtLabel(root, "Ready.");
|
|
strncpy(lbl->name, "status", MAX_WIDGET_NAME);
|
|
|
|
wgtHSeparator(root);
|
|
|
|
WidgetT *row = wgtHBox(root);
|
|
wgtLabel(row, "Name:");
|
|
wgtTextInput(row, 64);
|
|
|
|
WidgetT *btn = wgtButton(root, "Go");
|
|
btn->onClick = onButtonClick;
|
|
|
|
wgtInvalidate(root); // initial layout + paint
|
|
|
|
dvxRun(&ctx);
|
|
dvxShutdown(&ctx);
|
|
|
|
return 0;
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Application API (`dvxApp.h`)
|
|
|
|
### Lifecycle
|
|
|
|
```c
|
|
int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH,
|
|
int32_t preferredBpp);
|
|
```
|
|
Initialize VESA video, input, fonts, color scheme, and cursors. Finds a mode
|
|
matching the requested resolution and bit depth (8, 15, 16, or 32). Returns
|
|
0 on success, -1 on failure.
|
|
|
|
```c
|
|
void dvxRun(AppContextT *ctx);
|
|
```
|
|
Enter the main event loop. Handles mouse movement, button clicks, keyboard
|
|
input, window management, dirty-rectangle compositing, and LFB flush.
|
|
Returns when `dvxQuit()` is called or ESC is pressed.
|
|
|
|
```c
|
|
bool dvxUpdate(AppContextT *ctx);
|
|
```
|
|
Process one iteration of the event loop: poll input, dispatch events,
|
|
composite dirty regions, and flush. Returns `true` if the GUI is still
|
|
running, `false` when exit has been requested. Use this instead of
|
|
`dvxRun()` when embedding the GUI inside an existing main loop.
|
|
|
|
```c
|
|
void dvxShutdown(AppContextT *ctx);
|
|
```
|
|
Restore text mode, release LFB mapping, and free the backbuffer.
|
|
|
|
```c
|
|
void dvxQuit(AppContextT *ctx);
|
|
```
|
|
Request exit from the main loop. `dvxRun()` returns on the next iteration.
|
|
|
|
### Windows
|
|
|
|
```c
|
|
WindowT *dvxCreateWindow(AppContextT *ctx, const char *title,
|
|
int32_t x, int32_t y, int32_t w, int32_t h,
|
|
bool resizable);
|
|
```
|
|
Create a window at screen position (`x`, `y`) with outer dimensions `w` x `h`.
|
|
If `resizable` is true, the window gets resize handles and a maximize button.
|
|
The window is raised to the top and given focus. Returns NULL on failure.
|
|
|
|
After creation, set `win->userData` and install callbacks:
|
|
|
|
| Callback | Signature | When called |
|
|
|----------|-----------|-------------|
|
|
| `onPaint` | `void (WindowT *win, RectT *dirtyArea)` | Content needs redrawing |
|
|
| `onKey` | `void (WindowT *win, int32_t key, int32_t mod)` | Key press (focused window) |
|
|
| `onMouse` | `void (WindowT *win, int32_t x, int32_t y, int32_t buttons)` | Mouse event in content area |
|
|
| `onResize` | `void (WindowT *win, int32_t newW, int32_t newH)` | Window resized |
|
|
| `onClose` | `void (WindowT *win)` | Close button double-clicked |
|
|
| `onMenu` | `void (WindowT *win, int32_t menuId)` | Menu item selected |
|
|
| `onScroll` | `void (WindowT *win, ScrollbarOrientE orient, int32_t value)` | Scrollbar moved |
|
|
|
|
Mouse/key coordinates are relative to the content area. `buttons` is a
|
|
bitmask (bit 0 = left, bit 1 = right, bit 2 = middle).
|
|
|
|
```c
|
|
void dvxDestroyWindow(AppContextT *ctx, WindowT *win);
|
|
```
|
|
Remove a window from the stack and free its resources.
|
|
|
|
```c
|
|
void dvxSetTitle(AppContextT *ctx, WindowT *win, const char *title);
|
|
```
|
|
Change the title bar text.
|
|
|
|
```c
|
|
int32_t dvxSetWindowIcon(AppContextT *ctx, WindowT *win, const char *path);
|
|
```
|
|
Load a BMP, TGA, or PNG image and assign it as the window's minimized icon.
|
|
The image is converted to the display pixel format and scaled to 64x64.
|
|
Returns 0 on success.
|
|
|
|
### Invalidation
|
|
|
|
```c
|
|
void dvxInvalidateRect(AppContextT *ctx, WindowT *win,
|
|
int32_t x, int32_t y, int32_t w, int32_t h);
|
|
void dvxInvalidateWindow(AppContextT *ctx, WindowT *win);
|
|
```
|
|
Mark a region (or the entire content area) as needing repaint. The
|
|
compositor flushes dirty rectangles to the LFB on the next frame.
|
|
|
|
### Accessors
|
|
|
|
```c
|
|
DisplayT *dvxGetDisplay(AppContextT *ctx);
|
|
const BlitOpsT *dvxGetBlitOps(const AppContextT *ctx);
|
|
const BitmapFontT *dvxGetFont(const AppContextT *ctx);
|
|
const ColorSchemeT *dvxGetColors(const AppContextT *ctx);
|
|
```
|
|
|
|
### Window properties
|
|
|
|
Set these directly on the `WindowT` struct after creation:
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `maxW` | `int32_t` | -1 | Maximum width when maximized (-1 = screen width) |
|
|
| `maxH` | `int32_t` | -1 | Maximum height when maximized (-1 = screen height) |
|
|
| `userData` | `void *` | NULL | Application data pointer, passed through to callbacks |
|
|
|
|
### Content buffer
|
|
|
|
Each window has a persistent content backbuffer:
|
|
|
|
| Field | Description |
|
|
|-------|-------------|
|
|
| `contentBuf` | Pixel data in display format |
|
|
| `contentPitch` | Bytes per scanline |
|
|
| `contentW` | Width in pixels |
|
|
| `contentH` | Height in pixels |
|
|
|
|
Paint callbacks write directly into `contentBuf`. The compositor copies
|
|
visible portions to the screen backbuffer, then flushes dirty rects to
|
|
the LFB.
|
|
|
|
---
|
|
|
|
## Menu bars
|
|
|
|
```c
|
|
MenuBarT *wmAddMenuBar(WindowT *win);
|
|
```
|
|
Add a menu bar to a window. Call `wmUpdateContentRect()` and
|
|
`wmReallocContentBuf()` after adding the menu bar (the menu bar reduces
|
|
the content area).
|
|
|
|
```c
|
|
MenuT *wmAddMenu(MenuBarT *bar, const char *label);
|
|
```
|
|
Add a top-level menu to the bar. Returns a `MenuT *` to populate with items.
|
|
|
|
```c
|
|
void wmAddMenuItem(MenuT *menu, const char *label, int32_t id);
|
|
void wmAddMenuSeparator(MenuT *menu);
|
|
```
|
|
Add items to a menu. `id` is an application-defined command passed to
|
|
`onMenu`. Up to 16 items per menu, 8 menus per bar.
|
|
|
|
---
|
|
|
|
## Scrollbars
|
|
|
|
```c
|
|
ScrollbarT *wmAddVScrollbar(WindowT *win, int32_t min, int32_t max,
|
|
int32_t pageSize);
|
|
ScrollbarT *wmAddHScrollbar(WindowT *win, int32_t min, int32_t max,
|
|
int32_t pageSize);
|
|
```
|
|
Add a scrollbar to a window. `pageSize` controls the thumb size relative to
|
|
the range. Call `wmUpdateContentRect()` and `wmReallocContentBuf()` afterward.
|
|
|
|
The `onScroll` callback fires when the user drags the thumb or clicks the
|
|
arrow buttons / trough.
|
|
|
|
Widget windows manage their own scrollbars automatically -- do not add them
|
|
manually.
|
|
|
|
---
|
|
|
|
## Video and drawing (`dvxVideo.h`, `dvxDraw.h`)
|
|
|
|
These are lower-level APIs. Application code typically only needs `packColor`.
|
|
|
|
```c
|
|
uint32_t packColor(const DisplayT *d, uint8_t r, uint8_t g, uint8_t b);
|
|
```
|
|
Pack an RGB triple into the display's pixel format.
|
|
|
|
```c
|
|
void rectFill(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t w, int32_t h, uint32_t color);
|
|
```
|
|
Fill a rectangle with a solid color (clipped to the display clip rect).
|
|
|
|
```c
|
|
void drawBevel(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t w, int32_t h,
|
|
const BevelStyleT *style);
|
|
```
|
|
Draw a beveled frame. `BevelStyleT` specifies highlight, shadow, face colors
|
|
and border width.
|
|
|
|
```c
|
|
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);
|
|
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);
|
|
int32_t textWidth(const BitmapFontT *font, const char *text);
|
|
```
|
|
Draw text using the built-in 8-pixel-wide bitmap font. `opaque` controls
|
|
whether background pixels are drawn. `drawChar` returns the advance width.
|
|
|
|
```c
|
|
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);
|
|
```
|
|
Bulk-render a row of terminal character cells. `lineData` points to
|
|
`(char, attr)` byte pairs (2 bytes per cell). `palette` is a 16-entry
|
|
packed-color table. `blinkVisible` controls blink attribute visibility.
|
|
`cursorCol` is the column to draw inverted (-1 for no cursor). This is
|
|
much faster than calling `drawChar` per cell because clip bounds are
|
|
computed once for the whole row and there is no per-character function
|
|
call overhead.
|
|
|
|
```c
|
|
char accelParse(const char *text);
|
|
```
|
|
Parse an accelerator key from text with `&` markers (e.g. `"E&xit"` returns
|
|
`'x'`). Returns the lowercase accelerator character, or 0 if none found.
|
|
|
|
```c
|
|
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);
|
|
int32_t textWidthAccel(const BitmapFontT *font, const char *text);
|
|
```
|
|
Draw/measure text with `&` accelerator processing. The character after `&`
|
|
is underlined. `&&` produces a literal `&`. `textWidthAccel` returns the
|
|
width in pixels, excluding `&` markers.
|
|
|
|
```c
|
|
void drawFocusRect(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t w, int32_t h,
|
|
uint32_t color);
|
|
```
|
|
Draw a dotted rectangle outline (every other pixel). Used to indicate
|
|
keyboard focus on widgets.
|
|
|
|
```c
|
|
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);
|
|
```
|
|
Draw a 1-bit bitmap with AND/XOR masks (used for mouse cursors). Each row
|
|
is a `uint16_t`. Pixels where the AND mask is 0 are drawn using the XOR
|
|
data to select `fgColor` or `bgColor`.
|
|
|
|
```c
|
|
void drawHLine(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t w, uint32_t color);
|
|
void drawVLine(DisplayT *d, const BlitOpsT *ops,
|
|
int32_t x, int32_t y, int32_t h, uint32_t color);
|
|
```
|
|
|
|
```c
|
|
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);
|
|
```
|
|
Blit from a source buffer to the backbuffer with clipping.
|
|
|
|
```c
|
|
void setClipRect(DisplayT *d, int32_t x, int32_t y, int32_t w, int32_t h);
|
|
void resetClipRect(DisplayT *d);
|
|
```
|
|
|
|
---
|
|
|
|
## Widget system (`dvxWidget.h`)
|
|
|
|
An optional declarative layout system inspired by Amiga MUI and PC GEOS.
|
|
Widgets are arranged in a tree of VBox/HBox containers. A two-pass layout
|
|
engine (measure minimum sizes, then distribute space) handles geometry
|
|
automatically. Scrollbars appear when the window is too small for the
|
|
content.
|
|
|
|
### Initialization
|
|
|
|
```c
|
|
WidgetT *wgtInitWindow(AppContextT *ctx, WindowT *win);
|
|
```
|
|
Attach the widget system to a window. Returns the root container (a VBox
|
|
filling the content area). Installs `onPaint`, `onMouse`, `onKey`, and
|
|
`onResize` handlers on the window. Build the widget tree by passing the
|
|
returned root (or its children) as `parent` to the widget creation
|
|
functions below.
|
|
|
|
Call `wgtInvalidate(root)` after the tree is fully built to trigger the
|
|
initial layout and paint.
|
|
|
|
### Containers
|
|
|
|
```c
|
|
WidgetT *wgtVBox(WidgetT *parent); // vertical stack
|
|
WidgetT *wgtHBox(WidgetT *parent); // horizontal stack
|
|
WidgetT *wgtFrame(WidgetT *parent, const char *title); // titled border
|
|
```
|
|
Containers hold child widgets and control layout direction. `wgtFrame`
|
|
draws a styled border with a title label and lays out children vertically.
|
|
|
|
Frame styles (set `w->as.frame.style` after creation):
|
|
|
|
| Style | Description |
|
|
|-------|-------------|
|
|
| `FrameInE` | Beveled inward / sunken (default) |
|
|
| `FrameOutE` | Beveled outward / raised |
|
|
| `FrameFlatE` | Solid color line; set `w->as.frame.color` (0 = windowShadow) |
|
|
|
|
The title text is vertically centered on the top border line.
|
|
|
|
Container properties (set directly on the returned `WidgetT *`):
|
|
|
|
| Field | Type | Default | Description |
|
|
|-------|------|---------|-------------|
|
|
| `align` | `WidgetAlignE` | `AlignStartE` | Main-axis alignment when no children have weight |
|
|
| `spacing` | `int32_t` | 0 (4px) | Tagged size: gap between children |
|
|
| `padding` | `int32_t` | 0 (4px) | Tagged size: internal padding |
|
|
|
|
Alignment values:
|
|
|
|
| Value | HBox meaning | VBox meaning |
|
|
|-------|-------------|-------------|
|
|
| `AlignStartE` | left | top |
|
|
| `AlignCenterE` | center | center |
|
|
| `AlignEndE` | right | bottom |
|
|
|
|
### Widgets
|
|
|
|
```c
|
|
WidgetT *wgtLabel(WidgetT *parent, const char *text);
|
|
```
|
|
Static text label. Sized to fit its text.
|
|
|
|
```c
|
|
WidgetT *wgtButton(WidgetT *parent, const char *text);
|
|
```
|
|
Beveled push button with standard press/release behavior: the button
|
|
visually depresses on mouse-down, tracks the cursor while held, and
|
|
fires `onClick` on release if still over the button. Dragging off the
|
|
button cancels the click.
|
|
|
|
```c
|
|
WidgetT *wgtCheckbox(WidgetT *parent, const char *text);
|
|
```
|
|
Toggle checkbox. Read/write `w->as.checkbox.checked`. Set `onChange` to
|
|
be notified.
|
|
|
|
```c
|
|
WidgetT *wgtRadioGroup(WidgetT *parent);
|
|
WidgetT *wgtRadio(WidgetT *parent, const char *text);
|
|
```
|
|
Radio buttons with diamond-shaped indicators (visually distinct from
|
|
checkboxes). Create a group, then add options as children. The group
|
|
tracks the selected index in `w->as.radioGroup.selectedIdx`. Set
|
|
`onChange` on the group to be notified. Radio indices are auto-assigned.
|
|
|
|
```c
|
|
WidgetT *wgtTextInput(WidgetT *parent, int32_t maxLen);
|
|
```
|
|
Single-line text input field. `maxLen` is the buffer capacity. Default
|
|
weight is 100 (stretches to fill). Set `onChange` to be notified on edits.
|
|
|
|
Editing features: cursor movement (arrows, Home, End), insert/overwrite,
|
|
selection (Shift+arrows, Shift+Home/End, Ctrl+A, double-click word,
|
|
triple-click all), clipboard (Ctrl+C copy, Ctrl+V paste, Ctrl+X cut),
|
|
single-level undo (Ctrl+Z), and horizontal scrolling when text exceeds
|
|
the visible width. Mouse drag selection auto-scrolls when the cursor
|
|
reaches the edge of the field.
|
|
|
|
```c
|
|
WidgetT *wgtPasswordInput(WidgetT *parent, int32_t maxLen);
|
|
```
|
|
Password input field. Identical to `wgtTextInput` except characters are
|
|
displayed as bullets (CP437 `\xF9`). Copy and cut to clipboard are
|
|
disabled; paste is allowed. All other editing features work normally.
|
|
|
|
```c
|
|
WidgetT *wgtMaskedInput(WidgetT *parent, const char *mask);
|
|
```
|
|
Formatted input field with a fixed mask pattern. The mask string defines
|
|
the format: `#` accepts a digit, `A` accepts a letter, `*` accepts any
|
|
printable character. All other characters in the mask are literals that
|
|
are displayed but cannot be edited. The cursor skips over literal
|
|
positions automatically.
|
|
|
|
Example masks:
|
|
- `"(###) ###-####"` -- US phone number
|
|
- `"##/##/####"` -- date
|
|
- `"###-##-####"` -- SSN
|
|
|
|
The buffer always contains the full formatted text including literals.
|
|
`wgtGetText()` returns the formatted string. Supports selection
|
|
(Shift+arrows, Ctrl+A), clipboard (Ctrl+C, Ctrl+V, Ctrl+X), and
|
|
single-level undo (Ctrl+Z). The mask string must remain valid for the
|
|
widget's lifetime.
|
|
|
|
```c
|
|
WidgetT *wgtListBox(WidgetT *parent);
|
|
```
|
|
List box (basic -- set items with `wgtListBoxSetItems()`).
|
|
|
|
```c
|
|
WidgetT *wgtTextArea(WidgetT *parent, int32_t maxLen);
|
|
```
|
|
Multi-line text editor with vertical and horizontal scrollbars. Supports
|
|
all the same editing features as `wgtTextInput` plus multi-line selection
|
|
(Shift+Up/Down), Enter for newlines, and vertical/horizontal auto-scroll
|
|
during mouse drag selection. A horizontal scrollbar appears automatically
|
|
when any line exceeds the visible width. The vertical scrollbar is always
|
|
present.
|
|
|
|
### Dropdown and ComboBox
|
|
|
|
```c
|
|
WidgetT *wgtDropdown(WidgetT *parent);
|
|
void wgtDropdownSetItems(WidgetT *w, const char **items, int32_t count);
|
|
int32_t wgtDropdownGetSelected(const WidgetT *w);
|
|
void wgtDropdownSetSelected(WidgetT *w, int32_t idx);
|
|
```
|
|
Non-editable selection widget. Clicking the arrow button opens a popup
|
|
list below (or above if no room). Clicking the arrow again while the
|
|
popup is open closes it. Set `onChange` to be notified of selection
|
|
changes. The items array must remain valid for the widget's lifetime.
|
|
|
|
```c
|
|
WidgetT *wgtComboBox(WidgetT *parent, int32_t maxLen);
|
|
void wgtComboBoxSetItems(WidgetT *w, const char **items, int32_t count);
|
|
int32_t wgtComboBoxGetSelected(const WidgetT *w);
|
|
void wgtComboBoxSetSelected(WidgetT *w, int32_t idx);
|
|
```
|
|
Editable text field with a dropdown list. The text area accepts keyboard
|
|
input (same editing keys as `wgtTextInput`). Clicking the arrow button
|
|
toggles the popup; clicking the text area focuses it for editing.
|
|
Selecting an item copies its text into the edit buffer. Default weight
|
|
is 100.
|
|
|
|
### ProgressBar and Slider
|
|
|
|
```c
|
|
WidgetT *wgtProgressBar(WidgetT *parent);
|
|
void wgtProgressBarSetValue(WidgetT *w, int32_t value);
|
|
int32_t wgtProgressBarGetValue(const WidgetT *w);
|
|
```
|
|
Horizontal progress indicator. Value is 0--100 (percentage). The filled
|
|
portion draws left-to-right with the system highlight color.
|
|
|
|
```c
|
|
WidgetT *wgtSlider(WidgetT *parent, int32_t minVal, int32_t maxVal);
|
|
void wgtSliderSetValue(WidgetT *w, int32_t value);
|
|
int32_t wgtSliderGetValue(const WidgetT *w);
|
|
```
|
|
Draggable slider/trackbar. Horizontal by default; set
|
|
`w->as.slider.vertical = true` after creation for vertical orientation.
|
|
The thumb tracks the mouse while held. Set `onChange` to be notified.
|
|
|
|
### Spinner
|
|
|
|
```c
|
|
WidgetT *wgtSpinner(WidgetT *parent, int32_t minVal, int32_t maxVal, int32_t step);
|
|
void wgtSpinnerSetValue(WidgetT *w, int32_t value);
|
|
int32_t wgtSpinnerGetValue(const WidgetT *w);
|
|
void wgtSpinnerSetRange(WidgetT *w, int32_t minVal, int32_t maxVal);
|
|
void wgtSpinnerSetStep(WidgetT *w, int32_t step);
|
|
```
|
|
Numeric up/down input field with increment/decrement buttons. The text
|
|
area accepts direct keyboard entry of digits (and minus sign when the
|
|
minimum is negative). Up/Down arrows increment/decrement by `step`;
|
|
Page Up/Page Down by `step * 10`. Enter commits the typed value; Escape
|
|
reverts. The value is clamped to `[minVal, maxVal]` on every change.
|
|
|
|
Supports all single-line text editing features: cursor movement, selection
|
|
(Shift+arrows, Ctrl+A, double/triple-click), clipboard (Ctrl+C/V/X),
|
|
and single-level undo (Ctrl+Z). Non-numeric input is filtered out.
|
|
|
|
The widget has a sunken text area with up/down arrow buttons on the right.
|
|
Clicking the top half of the button area increments; the bottom half
|
|
decrements. Set `onChange` to be notified of value changes.
|
|
|
|
### TabControl
|
|
|
|
```c
|
|
WidgetT *wgtTabControl(WidgetT *parent);
|
|
WidgetT *wgtTabPage(WidgetT *parent, const char *title);
|
|
void wgtTabControlSetActive(WidgetT *w, int32_t idx);
|
|
int32_t wgtTabControlGetActive(const WidgetT *w);
|
|
```
|
|
Tabbed container. Create a tab control, then add pages as children.
|
|
Each page is a VBox that holds its own widget subtree. Only the active
|
|
page is visible and receives layout; inactive pages are hidden. Clicking
|
|
a tab header switches the active page.
|
|
|
|
### StatusBar and Toolbar
|
|
|
|
```c
|
|
WidgetT *wgtStatusBar(WidgetT *parent);
|
|
WidgetT *wgtToolbar(WidgetT *parent);
|
|
```
|
|
Horizontal containers with specialized chrome. StatusBar draws a sunken
|
|
panel background; Toolbar draws a raised background. Both use horizontal
|
|
layout with default spacing. Add child widgets (labels, buttons, etc.)
|
|
as with any HBox. StatusBar children with `weight > 0` stretch to fill.
|
|
|
|
### TreeView
|
|
|
|
```c
|
|
WidgetT *wgtTreeView(WidgetT *parent);
|
|
WidgetT *wgtTreeItem(WidgetT *parent, const char *text);
|
|
void wgtTreeItemSetExpanded(WidgetT *w, bool expanded);
|
|
bool wgtTreeItemIsExpanded(const WidgetT *w);
|
|
WidgetT *wgtTreeViewGetSelected(const WidgetT *w);
|
|
void wgtTreeViewSetSelected(WidgetT *w, WidgetT *item);
|
|
```
|
|
Hierarchical tree with expand/collapse support. Create a tree view, then
|
|
add items as children. Nest items by adding them as children of other
|
|
items. Items with children show a `[+]`/`[-]` expand box.
|
|
|
|
The tree view manages its own internal scrollbars: a vertical scrollbar
|
|
appears when expanded items exceed the visible height, and a horizontal
|
|
scrollbar appears when item text extends beyond the visible width. Both
|
|
scrollbars have arrow buttons, proportional thumbs, and page
|
|
scrolling on trough clicks.
|
|
|
|
Default weight is 100. Set `onClick` on individual tree items to handle
|
|
selection, or `onChange` to be notified of expand/collapse.
|
|
|
|
`wgtTreeViewGetSelected` returns the currently selected tree item (or NULL).
|
|
`wgtTreeViewSetSelected` sets the selection programmatically.
|
|
|
|
### Image
|
|
|
|
```c
|
|
WidgetT *wgtImage(WidgetT *parent, uint8_t *data,
|
|
int32_t w, int32_t h, int32_t pitch);
|
|
WidgetT *wgtImageFromFile(WidgetT *parent, const char *path);
|
|
void wgtImageSetData(WidgetT *w, uint8_t *data,
|
|
int32_t imgW, int32_t imgH, int32_t pitch);
|
|
```
|
|
Display a bitmap image. `wgtImage` takes ownership of the pixel buffer
|
|
(freed on destroy). `wgtImageFromFile` loads any format supported by
|
|
stb_image and converts to the display pixel format. Set `onClick` to
|
|
make the image clickable.
|
|
|
|
### ImageButton
|
|
|
|
```c
|
|
WidgetT *wgtImageButton(WidgetT *parent, uint8_t *data,
|
|
int32_t w, int32_t h, int32_t pitch);
|
|
void wgtImageButtonSetData(WidgetT *w, uint8_t *data,
|
|
int32_t imgW, int32_t imgH, int32_t pitch);
|
|
```
|
|
Push button that displays an image instead of a text caption. Behaves
|
|
identically to `wgtButton` -- visually depresses on mouse-down, tracks the
|
|
cursor while held, and fires `onClick` on release if still over the button.
|
|
The image is centered on the button face with a 2px bevel border and no
|
|
extra padding. When pressed, the image shifts 1px down and right.
|
|
|
|
`wgtImageButton` takes ownership of the pixel buffer (freed on destroy).
|
|
`wgtImageButtonSetData` replaces the image data, freeing the previous buffer.
|
|
The pixel buffer must be in display pixel format (use `packColor()` and the
|
|
display's `bytesPerPixel` to prepare it).
|
|
|
|
### Canvas
|
|
|
|
```c
|
|
WidgetT *wgtCanvas(WidgetT *parent, int32_t w, int32_t h);
|
|
```
|
|
Drawable bitmap canvas with a sunken bevel border. Supports both
|
|
interactive freehand drawing (mouse strokes are Bresenham-interpolated)
|
|
and programmatic drawing from the API.
|
|
|
|
```c
|
|
void wgtCanvasClear(WidgetT *w, uint32_t color);
|
|
void wgtCanvasSetPenColor(WidgetT *w, uint32_t color);
|
|
void wgtCanvasSetPenSize(WidgetT *w, int32_t size);
|
|
int32_t wgtCanvasSave(WidgetT *w, const char *path);
|
|
int32_t wgtCanvasLoad(WidgetT *w, const char *path);
|
|
```
|
|
`wgtCanvasSave` writes the canvas to a PNG file (converting from display
|
|
pixel format to RGB). `wgtCanvasLoad` reads any image format supported by
|
|
stb_image and converts it to display pixel format.
|
|
|
|
Programmatic drawing primitives (all coordinates are in canvas space):
|
|
|
|
```c
|
|
void wgtCanvasSetPixel(WidgetT *w, int32_t x, int32_t y, uint32_t color);
|
|
uint32_t wgtCanvasGetPixel(const WidgetT *w, int32_t x, int32_t y);
|
|
void wgtCanvasDrawLine(WidgetT *w, int32_t x0, int32_t y0, int32_t x1, int32_t y1);
|
|
void wgtCanvasDrawRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t height);
|
|
void wgtCanvasFillRect(WidgetT *w, int32_t x, int32_t y, int32_t width, int32_t height);
|
|
void wgtCanvasFillCircle(WidgetT *w, int32_t cx, int32_t cy, int32_t radius);
|
|
```
|
|
`SetPixel`/`GetPixel` take explicit colors. `DrawLine` uses the current
|
|
pen color and pen size. `DrawRect` draws a 1px outline, `FillRect` fills
|
|
solid, and `FillCircle` fills a circle -- all using the current pen
|
|
color. All operations clip to the canvas bounds. Colors are in display
|
|
pixel format (use `packColor()` to create them).
|
|
|
|
### ANSI Terminal
|
|
|
|
```c
|
|
WidgetT *wgtAnsiTerm(WidgetT *parent, int32_t cols, int32_t rows);
|
|
```
|
|
ANSI BBS terminal emulator widget. Displays a character grid (default
|
|
80x25 if cols/rows are 0) with full ANSI escape sequence support and a
|
|
16-color CGA palette. The terminal has a 2px sunken bevel border and a
|
|
vertical scrollbar for scrollback history. Supports mouse text selection
|
|
(click and drag), Ctrl+C to copy selected text (sends `^C` to the
|
|
terminal when nothing is selected), and Ctrl+V to paste clipboard text
|
|
through the comm interface.
|
|
|
|
ANSI escape sequences supported:
|
|
|
|
| Sequence | Description |
|
|
|----------|-------------|
|
|
| `ESC[H` / `ESC[f` | Cursor position (CUP/HVP) |
|
|
| `ESC[A/B/C/D` | Cursor up/down/forward/back |
|
|
| `ESC[J` | Erase display (0=to end, 1=to start, 2=all) |
|
|
| `ESC[K` | Erase line (0=to end, 1=to start, 2=all) |
|
|
| `ESC[m` | SGR: colors 30-37/40-47, bright 90-97/100-107, bold(1), blink(5), reverse(7), reset(0) |
|
|
| `ESC[s` / `ESC[u` | Save / restore cursor position |
|
|
| `ESC[S` / `ESC[T` | Scroll up / down |
|
|
| `ESC[L` / `ESC[M` | Insert / delete lines |
|
|
| `ESC[?7h/l` | Enable / disable auto-wrap |
|
|
| `ESC[?25h/l` | Show / hide cursor |
|
|
|
|
Control characters: CR, LF, BS, TAB, BEL (ignored).
|
|
|
|
```c
|
|
void wgtAnsiTermWrite(WidgetT *w, const uint8_t *data, int32_t len);
|
|
```
|
|
Feed data through the ANSI parser. Use this to display `.ANS` files or
|
|
inject content without a communications link.
|
|
|
|
```c
|
|
void wgtAnsiTermClear(WidgetT *w);
|
|
```
|
|
Clear the screen, push all visible lines to scrollback, and reset the
|
|
cursor to the home position.
|
|
|
|
```c
|
|
void wgtAnsiTermSetComm(WidgetT *w, void *ctx,
|
|
int32_t (*readFn)(void *, uint8_t *, int32_t),
|
|
int32_t (*writeFn)(void *, const uint8_t *, int32_t));
|
|
```
|
|
Set the communications interface. `readFn` should return bytes read
|
|
(0 if none available). `writeFn` sends bytes. Pass NULL function
|
|
pointers for a disconnected / display-only terminal.
|
|
|
|
When connected, keyboard input is translated to ANSI sequences and sent
|
|
via `writeFn` (arrows become `ESC[A`..`ESC[D`, etc.).
|
|
|
|
```c
|
|
int32_t wgtAnsiTermPoll(WidgetT *w);
|
|
```
|
|
Poll the comm interface for incoming data and process it through the
|
|
ANSI parser. Also handles cursor blink and text blink timers. Returns
|
|
the number of bytes read. When using `dvxUpdate()`, terminal polling
|
|
is handled automatically -- call this manually only when running your
|
|
own event loop.
|
|
|
|
```c
|
|
int32_t wgtAnsiTermRepaint(WidgetT *w, int32_t *outY, int32_t *outH);
|
|
```
|
|
Fast repaint: renders only dirty rows directly into the window's content
|
|
buffer, bypassing the full widget paint pipeline (no clear, no relayout,
|
|
no other widgets). Returns the number of rows repainted (0 if nothing
|
|
was dirty). If `outY` and `outH` are non-NULL, they receive the
|
|
content-buffer-relative Y coordinate and height of the repainted region,
|
|
for targeted dirty-rect invalidation. Uses `drawTermRow()` internally
|
|
for efficient bulk rendering. When using `dvxUpdate()`, this is called
|
|
automatically after `wgtAnsiTermPoll()`.
|
|
|
|
```c
|
|
void wgtAnsiTermSetScrollback(WidgetT *w, int32_t maxLines);
|
|
```
|
|
Set the scrollback buffer size (default 500 lines). Clears any existing
|
|
scrollback. Lines scroll into the buffer when they leave the top of the
|
|
screen or when the screen is cleared (`ESC[2J` / `wgtAnsiTermClear`).
|
|
|
|
A vertical scrollbar appears automatically when there is scrollback
|
|
content. Click the arrow buttons for single-line scrolling, or the
|
|
trough for page scrolling. The view auto-follows live output unless the
|
|
user has scrolled back.
|
|
|
|
### Spacing and dividers
|
|
|
|
```c
|
|
WidgetT *wgtSpacer(WidgetT *parent);
|
|
```
|
|
Invisible spacer. Default weight is 100 -- pushes siblings apart.
|
|
|
|
```c
|
|
WidgetT *wgtHSeparator(WidgetT *parent); // horizontal line
|
|
WidgetT *wgtVSeparator(WidgetT *parent); // vertical line
|
|
```
|
|
Visual divider lines (shadow + highlight, 2px).
|
|
|
|
### Size specifications
|
|
|
|
Size fields (`minW`, `minH`, `maxW`, `maxH`, `prefW`, `prefH`, `spacing`,
|
|
`padding`) accept tagged values created with:
|
|
|
|
```c
|
|
wgtPixels(120) // 120 pixels
|
|
wgtChars(15) // 15 character widths
|
|
wgtPercent(50) // 50% of parent
|
|
```
|
|
|
|
A raw `0` means auto (use the widget's natural/computed size).
|
|
|
|
### Weight
|
|
|
|
The `weight` field controls how extra space is distributed among siblings.
|
|
When a container is larger than its children's combined minimum size, the
|
|
surplus is divided proportionally by weight.
|
|
|
|
- `weight = 0` -- fixed size, does not stretch (default for most widgets)
|
|
- `weight = 100` -- normal stretch (default for spacers and text inputs)
|
|
- Relative values work: weights of 100, 200, 100 give a 1:2:1 split
|
|
|
|
When all children have weight 0, the container's `align` property
|
|
determines where children are placed within the extra space.
|
|
|
|
### Operations
|
|
|
|
```c
|
|
void wgtSetText(WidgetT *w, const char *text);
|
|
const char *wgtGetText(const WidgetT *w);
|
|
```
|
|
Get/set text for labels, buttons, checkboxes, radios, text inputs,
|
|
password inputs, masked inputs, combo boxes, and dropdowns.
|
|
|
|
```c
|
|
void wgtSetEnabled(WidgetT *w, bool enabled);
|
|
void wgtSetVisible(WidgetT *w, bool visible);
|
|
```
|
|
Disabled widgets are drawn grayed out and ignore input. Hidden widgets
|
|
are excluded from layout.
|
|
|
|
```c
|
|
void wgtInvalidate(WidgetT *w);
|
|
```
|
|
Trigger a full relayout and repaint of the widget tree. Call after
|
|
modifying widget properties, adding/removing widgets, or changing text.
|
|
|
|
```c
|
|
WidgetT *wgtFind(WidgetT *root, const char *name);
|
|
```
|
|
Search the subtree for a widget by name. Set `w->name` (up to 31 chars)
|
|
to make a widget findable.
|
|
|
|
```c
|
|
void wgtDestroy(WidgetT *w);
|
|
```
|
|
Remove a widget and all its children from the tree and free memory.
|
|
|
|
```c
|
|
void wgtSetDebugLayout(bool enabled);
|
|
```
|
|
When enabled, draws 1px neon-colored borders around all layout containers
|
|
so their bounds are visible. Each container gets a distinct color derived
|
|
from its pointer.
|
|
|
|
### Layout and paint internals
|
|
|
|
These are called automatically by `wgtInvalidate()`, but are available
|
|
for manual use when embedding the widget system in a custom event loop.
|
|
|
|
```c
|
|
int32_t wgtResolveSize(int32_t taggedSize, int32_t parentSize, int32_t charWidth);
|
|
```
|
|
Convert a tagged size (from `wgtPixels`, `wgtChars`, or `wgtPercent`) to
|
|
a pixel value given the parent's size and the font's character width.
|
|
|
|
```c
|
|
void wgtLayout(WidgetT *root, int32_t availW, int32_t availH,
|
|
const BitmapFontT *font);
|
|
```
|
|
Run the two-pass layout engine on the widget tree: measure minimum sizes
|
|
bottom-up, then distribute available space top-down. Sets `x`, `y`, `w`,
|
|
`h` on every widget.
|
|
|
|
```c
|
|
void wgtPaint(WidgetT *root, DisplayT *d, const BlitOpsT *ops,
|
|
const BitmapFontT *font, const ColorSchemeT *colors);
|
|
```
|
|
Paint the entire widget tree into the window's content buffer.
|
|
|
|
### List box operations
|
|
|
|
```c
|
|
void wgtListBoxSetItems(WidgetT *w, const char **items, int32_t count);
|
|
int32_t wgtListBoxGetSelected(const WidgetT *w);
|
|
void wgtListBoxSetSelected(WidgetT *w, int32_t idx);
|
|
```
|
|
|
|
### ListView
|
|
|
|
```c
|
|
WidgetT *wgtListView(WidgetT *parent);
|
|
void wgtListViewSetColumns(WidgetT *w, const ListViewColT *cols, int32_t count);
|
|
void wgtListViewSetData(WidgetT *w, const char **cellData, int32_t rowCount);
|
|
int32_t wgtListViewGetSelected(const WidgetT *w);
|
|
void wgtListViewSetSelected(WidgetT *w, int32_t idx);
|
|
```
|
|
Multi-column list with sortable headers, resizable columns, and single or
|
|
multi-select support. Column definitions use `ListViewColT`:
|
|
|
|
```c
|
|
typedef struct {
|
|
const char *title;
|
|
int32_t width; // tagged size (wgtPixels/wgtChars/wgtPercent)
|
|
ListViewAlignE align; // ListViewAlignLeftE, CenterE, or RightE
|
|
} ListViewColT;
|
|
```
|
|
|
|
Column widths support tagged sizes (`wgtPixels`, `wgtChars`, `wgtPercent`).
|
|
Cell data is a flat array of strings in row-major order (row0col0, row0col1,
|
|
..., row1col0, ...). Both the column and data arrays must remain valid for
|
|
the widget's lifetime.
|
|
|
|
Clicking a column header sorts the list. An arrow indicator shows the
|
|
current sort direction. Column borders can be dragged to resize. Vertical
|
|
and horizontal scrollbars appear automatically when needed.
|
|
|
|
```c
|
|
void wgtListViewSetSort(WidgetT *w, int32_t col, ListViewSortE dir);
|
|
void wgtListViewSetHeaderClickCallback(WidgetT *w,
|
|
void (*cb)(WidgetT *w, int32_t col, ListViewSortE dir));
|
|
```
|
|
Programmatic sort control. The header click callback fires after the sort
|
|
direction is updated, allowing custom sort logic.
|
|
|
|
```c
|
|
void wgtListViewSetMultiSelect(WidgetT *w, bool multi);
|
|
bool wgtListViewIsItemSelected(const WidgetT *w, int32_t idx);
|
|
void wgtListViewSetItemSelected(WidgetT *w, int32_t idx, bool selected);
|
|
void wgtListViewSelectAll(WidgetT *w);
|
|
void wgtListViewClearSelection(WidgetT *w);
|
|
```
|
|
Multi-select mode supports Ctrl+click to toggle individual items and
|
|
Shift+click for range selection. Default weight is 100.
|
|
|
|
### ScrollPane
|
|
|
|
```c
|
|
WidgetT *wgtScrollPane(WidgetT *parent);
|
|
```
|
|
Scrollable container for child widgets. Children are laid out vertically
|
|
(like a VBox) at their natural size. Vertical and horizontal scrollbars
|
|
appear automatically when the content exceeds the visible area.
|
|
|
|
Mouse clicks on the scrollbar arrows scroll by one line/character; clicks
|
|
on the trough scroll by one page. Clicks on the content area are forwarded
|
|
to child widgets. Keyboard scrolling: Up/Down arrows, Page Up/Down,
|
|
Home/End for vertical; Left/Right arrows for horizontal.
|
|
|
|
Set `padding` and `spacing` to control internal layout. Default weight
|
|
is 100.
|
|
|
|
---
|
|
|
|
## Types reference (`dvxTypes.h`)
|
|
|
|
### WindowT
|
|
|
|
Core window structure. Key fields:
|
|
|
|
| Field | Type | Description |
|
|
|-------|------|-------------|
|
|
| `id` | `int32_t` | Unique window identifier |
|
|
| `x`, `y`, `w`, `h` | `int32_t` | Outer frame position and size |
|
|
| `contentX`, `contentY` | `int32_t` | Content area offset within frame |
|
|
| `contentW`, `contentH` | `int32_t` | Content area dimensions |
|
|
| `contentBuf` | `uint8_t *` | Pixel buffer (display format) |
|
|
| `contentPitch` | `int32_t` | Bytes per scanline in content buffer |
|
|
| `title` | `char[128]` | Title bar text |
|
|
| `visible` | `bool` | Window is shown |
|
|
| `focused` | `bool` | Window has input focus |
|
|
| `minimized` | `bool` | Window is minimized to icon |
|
|
| `maximized` | `bool` | Window is maximized |
|
|
| `resizable` | `bool` | Window has resize handles |
|
|
| `maxW`, `maxH` | `int32_t` | Max dimensions for maximize (-1 = screen) |
|
|
| `userData` | `void *` | Application data pointer |
|
|
|
|
### ColorSchemeT
|
|
|
|
All colors are pre-packed via `packColor()`:
|
|
|
|
| Field | Usage |
|
|
|-------|-------|
|
|
| `desktop` | Desktop background |
|
|
| `windowFace` | Window frame fill |
|
|
| `windowHighlight` | Bevel light edge |
|
|
| `windowShadow` | Bevel dark edge |
|
|
| `activeTitleBg/Fg` | Focused title bar |
|
|
| `inactiveTitleBg/Fg` | Unfocused title bar |
|
|
| `contentBg/Fg` | Window content area |
|
|
| `menuBg/Fg` | Menu bar and popups |
|
|
| `menuHighlightBg/Fg` | Highlighted menu item |
|
|
| `buttonFace` | Button interior |
|
|
| `scrollbarBg/Fg/Trough` | Scrollbar elements |
|
|
|
|
### BitmapFontT
|
|
|
|
Fixed-width bitmap font (8px wide, 14 or 16px tall). Glyphs are packed
|
|
1bpp, `charHeight` bytes per glyph, MSB-first.
|
|
|
|
### BevelStyleT
|
|
|
|
```c
|
|
typedef struct {
|
|
uint32_t highlight; // top/left edge color
|
|
uint32_t shadow; // bottom/right edge color
|
|
uint32_t face; // interior fill (0 = no fill)
|
|
int32_t width; // border thickness in pixels
|
|
} BevelStyleT;
|
|
```
|
|
|
|
---
|
|
|
|
## Window chrome
|
|
|
|
Windows use a Motif/GEOS-style frame:
|
|
|
|
- 4px beveled outer border with perpendicular groove breaks
|
|
- 20px title bar (dark charcoal background when focused)
|
|
- Close button on the left edge (requires double-click)
|
|
- Minimize button on the right edge (always present)
|
|
- Maximize button to the left of minimize (resizable windows only)
|
|
- Optional menu bar below the title bar (20px)
|
|
- Optional scrollbars along the right and bottom edges (16px)
|
|
|
|
Minimized windows appear as 64x64 beveled icons along the bottom of the
|
|
screen. If a window has an icon image set via `dvxSetWindowIcon()`, that
|
|
image is shown; otherwise a nearest-neighbor-scaled thumbnail of the
|
|
window's content buffer is used. Thumbnails are refreshed automatically
|
|
when the window's content changes, with updates staggered across frames
|
|
so only one icon redraws per interval. Double-click an icon to restore.
|
|
|
|
---
|
|
|
|
## Hardware requirements
|
|
|
|
- 486 or later CPU
|
|
- VESA VBE 2.0+ compatible video card with linear framebuffer support
|
|
- PS/2 mouse (or compatible mouse driver)
|
|
- DPMI host (CWSDPMI, Windows DOS box, DOSBox, 86Box)
|
|
|
|
Tested on 86Box with PCI video cards. DOSBox is a trusted reference
|
|
platform.
|