# DVX Shell Applications

Every DVX application is a DXE3 module packaged as a `.app` file,
installed under `bin/apps/kpunch/<name>/<name>.app`. The Program
Manager scans this directory at startup and displays each discovered
app as a launchable icon on the desktop.

This directory holds the source for the bundled applications plus
the BASIC-based sample apps. Two flavours of app live side by side:

* **C apps** -- written directly against the DVX SDK headers,
  compiled to a DXE3 by `dxe3gen`. See `progman/`, `clock/`,
  `dvxdemo/`, `cpanel/`, `dvxhelp/`.
* **BASIC apps** -- `.dbp` projects compiled to `.app` files by the
  host-side `bascomp`. The compiler links the BASIC bytecode into a
  copy of `basstub.app`, which acts as the runtime host. See
  `iconed/`, `notepad/`, `imgview/`, `basdemo/`, `resedit/`,
  `dvxhelp/helpedit/`.

The rest of this document covers writing a C app against the SDK.
For BASIC apps, see `dvxbasic/README.md`.


## DXE App Contract

Every `.app` binary exports two required symbols and one optional
symbol:

```c
AppDescriptorT appDescriptor;                    // required
int32_t        appMain(DxeAppContextT *ctx);     // required
void           appShutdown(void);                // optional
```

### `appDescriptor`

A statically-initialised struct read by the shell at load time to
decide how to launch the app:

```c
typedef struct {
    char    name[SHELL_APP_NAME_MAX];    // display name (<= 64 chars)
    bool    hasMainLoop;                 // see below
    bool    multiInstance;               // may have multiple copies open
    int32_t stackSize;                   // SHELL_STACK_DEFAULT or byte count
    int32_t priority;                    // TS_PRIORITY_* for main-loop apps
} AppDescriptorT;
```

Example (from `clock/clock.c`):

```c
AppDescriptorT appDescriptor = {
    .name          = "Clock",
    .hasMainLoop   = true,
    .multiInstance = true,
    .stackSize     = SHELL_STACK_DEFAULT,
    .priority      = TS_PRIORITY_LOW
};
```

### `appMain`

Entry point. The shell calls it with a `DxeAppContextT` that exposes
the shell's GUI context, the app's ID, its install directory, a
writable config directory, launch arguments, and a help-topic query
callback for F1.

Returning from `appMain` signals that the app has finished; the
shell unloads the DXE, frees per-app memory, and reclaims the app
slot.

### `appShutdown`

Called by the shell when the app is force-killed (by the Task
Manager) or when the shell is shutting down with this app still
running. Main-loop apps use it to set a flag that their main loop
observes, so the loop exits cleanly and `appMain` can return.


## App Types

### Callback-only apps (`hasMainLoop = false`)

`appMain` creates windows, registers callbacks, and returns 0. The
shell drives all further work by invoking those callbacks in
response to user input and timers. No dedicated task is allocated;
no per-app stack is consumed. The app's lifetime ends when the last
window closes (or when every callback has released all references).

Use this pattern for event-driven UI: Notepad, Program Manager, DVX
Demo, Control Panel, Image Viewer.

### Main-loop apps (`hasMainLoop = true`)

The shell creates a cooperative task for the app and calls
`appMain` from inside it. `appMain` runs a loop that calls
`tsYield()` periodically to share the CPU. Exit by breaking out of
the loop and returning.

Use this pattern when the app needs continuous background work that
does not map cleanly onto event callbacks: Clock (polls the system
clock every second), terminal emulators, games.


## Resource Conventions

Apps attach resources to their `.app` binary using `dvxres build`
(see `src/tools/README.md`). The standard resource names are:

| Name          | Type   | Meaning |
|---------------|--------|---------|
| `icon32`      | icon   | 32x32 BMP shown in Program Manager and the Task Manager. |
| `name`        | text   | Human-readable display name (overrides `appDescriptor.name` for UI where available). |
| `author`      | text   | Author / maintainer name. |
| `publisher`   | text   | Publisher or studio. |
| `copyright`   | text   | Copyright notice. |
| `version`     | text   | Version string, free-form. |
| `description` | text   | One-sentence description shown in About dialogs. |
| `helpfile`    | text   | Optional relative path to a `.hlp` file for F1 context help. |

Additional application-specific resources may be attached with any
unique name. The runtime reads them via
`dvxResOpen(appPath)` / `dvxResRead(handle, name, &size)` /
`dvxResClose(handle)`.

Typical `.res` manifest:

```
# clock.res
icon32      icon  icon32.bmp
name        text  "Clock"
author      text  "Scott Duensing"
copyright   text  "Copyright 2026 Scott Duensing"
publisher   text  "Kangaroo Punch Studios"
description text  "Digital clock with date display"
```


## Bundled Applications

### Program Manager (progman)

| | |
|---|---|
| File | `apps/kpunch/progman/progman.app` |
| Type | Callback-only |
| Multi-instance | No |

The desktop. Recursively scans `apps/` for `.app` files and displays
them as a launchable grid with icons, names, and publishers. Double
click or Enter to launch. Includes a Help menu with the system help
viewer and the About / System Info dialog. Registers with
`shellRegisterDesktopUpdate()` so the grid refreshes when apps are
loaded, terminated, or crash.

Widget headers used: `box/box.h`, `button/button.h`, `label/label.h`,
`statusBar/statBar.h`, `textInput/textInpt.h`, `imageButton/imgBtn.h`,
`scrollPane/scrlPane.h`, `wrapBox/wrapBox.h`.

### Notepad (notepad, BASIC)

| | |
|---|---|
| File | `apps/kpunch/notepad/notepad.app` |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |

Plain-text editor with File menu (New, Open, Save, Save As) and Edit
menu (Cut, Copy, Paste, Select All). Built from a BASIC project
(`notepad.dbp` + `notepad.frm`); demonstrates the form designer,
TextInput widget, and common dialog integration.

### Clock (clock)

| | |
|---|---|
| File | `apps/kpunch/clock/clock.app` |
| Type | Main-loop |
| Multi-instance | Yes |

Digital clock showing time and date. Polls the system clock every
second and invalidates the window to trigger a repaint. Uses the raw
`onPaint` callback (no widgets) to draw centered text. Reference
implementation for main-loop apps.

### DVX Demo (dvxdemo)

| | |
|---|---|
| File | `apps/kpunch/dvxdemo/dvxdemo.app` |
| Type | Callback-only |
| Multi-instance | No |

Widget toolkit showcase. Opens multiple windows demonstrating
virtually every widget type:

* Main window -- raw paint callbacks (gradients, patterns, text)
* Widget demo -- form widgets (TextInput, Checkbox, Radio, ListBox)
* Controls window -- tabbed advanced widgets (Dropdown,
  ProgressBar, Slider, Spinner, TreeView, ListView, ScrollPane,
  Toolbar, Canvas, Splitter, Image)
* Terminal window -- AnsiTerm widget

Resources include `logo.bmp`, `new.bmp`, `open.bmp`, `sample.bmp`,
`save.bmp`. Reference implementation for widget-based UIs.

### Control Panel (cpanel)

| | |
|---|---|
| File | `apps/kpunch/cpanel/cpanel.app` |
| Type | Callback-only |
| Multi-instance | No |

System configuration with four tabs:

* **Mouse** -- scroll direction, wheel speed, double-click speed,
  acceleration, cursor speed
* **Colors** -- every system colour with live preview; theme load
  and save
* **Desktop** -- wallpaper image and display mode
* **Video** -- resolution and colour depth switching

Changes preview live. OK writes to `CONFIG/DVX.INI`; Cancel reverts
to the snapshot taken when the panel opened.

### Image Viewer (imgview, BASIC)

| | |
|---|---|
| File | `apps/kpunch/imgview/imgview.app` |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |

Displays BMP, PNG, JPEG, and GIF images scaled to fit the window
with aspect ratio preserved. Resize to zoom. Open via the File menu
or via launch arguments. Built from a BASIC project using the
Canvas widget.

### DVX BASIC (dvxbasic)

| | |
|---|---|
| File | `apps/kpunch/dvxbasic/dvxbasic.app` |
| Type | Callback-only |
| Multi-instance | No |

Visual Basic 3 compatible IDE: form designer, per-procedure code
editor, project manager, compiler, and runtime VM. See
`dvxbasic/README.md` for a detailed architecture description.

`dvxbasic/` also builds:

* `bin/libs/kpunch/basrt/basrt.lib` -- the BASIC runtime (VM +
  values) as a separately loadable library, so compiled BASIC apps
  do not carry their own copy of the runtime.
* `bin/apps/kpunch/dvxbasic/basstub.app` -- the stub used as the
  template for every compiled BASIC app.

### DVX Help Viewer (dvxhelp)

| | |
|---|---|
| File | `apps/kpunch/dvxhelp/dvxhelp.app` |
| Type | Callback-only |
| Multi-instance | Yes |

Renders compiled `.hlp` files produced by `dvxhlpc`. Supports table
of contents, keyword index, full-text search (trigram), hyperlinks,
and inline images.

### Icon Editor (iconed, BASIC)

| | |
|---|---|
| File | `apps/kpunch/iconed/iconed.app` |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |

Paint-program-style editor for creating 32x32 BMP icons. Pen /
eraser / fill tools, 16-colour palette, BMP save / load.

### Help Editor (helpedit, BASIC)

| | |
|---|---|
| File | `apps/kpunch/dvxhelp/helpedit.app` |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |

Editor for `.dhs` help source files with syntax-aware controls. Runs
the compiled system help viewer by default for live preview.

### Resource Editor (resedit, BASIC)

| | |
|---|---|
| File | `apps/kpunch/resedit/resedit.app` |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |

GUI wrapper around `dvxres`: open a `.app` / `.wgt` / `.lib`,
browse its resources, add, replace, extract, or remove them.

### BASIC Demo (basdemo, BASIC)

| | |
|---|---|
| File | `apps/kpunch/basdemo/basdemo.app` |
| Type | BASIC (main-loop via basstub) |
| Multi-instance | No |

Gallery of short BASIC programs demonstrating the language and the
form designer. Intended as sample source for reading.


## Build

```
make              # build every app (C apps + BASIC apps)
make <appname>    # build a single app
make clean        # remove all app build artifacts
```

The `apps/kpunch/Makefile` orchestrates both C and BASIC builds:

* **C apps** compile each `<app>/<app>.c` to an object file, run
  `dxe3gen -U` on it to produce `<app>.app`, then attach resources
  with `dvxres build` if a `.res` manifest exists.
* **BASIC apps** run `bascomp <app>.dbp -o <app>.app -release`,
  which handles project-file parsing, compilation, resource
  attachment, and linking into `basstub.app`.

Build output goes to `bin/apps/kpunch/<app>/<app>.app`.


## Writing a New C App

Minimal skeleton:

```c
#include "dvxApp.h"
#include "dvxWgt.h"
#include "shellApp.h"

#include <stdint.h>
#include <stdbool.h>

// Prototypes
static int32_t appMainImpl(DxeAppContextT *ctx);
static void    onClose(WindowT *win);

// Required descriptor
AppDescriptorT appDescriptor = {
    .name          = "My App",
    .hasMainLoop   = false,
    .multiInstance = false,
    .stackSize     = SHELL_STACK_DEFAULT,
    .priority      = 0
};


static void onClose(WindowT *win) {
    (void)win;
    // Callback-only apps: nothing to do; the shell reaps us when
    // the last window closes.
}


int32_t appMain(DxeAppContextT *ctx) {
    return appMainImpl(ctx);
}


static int32_t appMainImpl(DxeAppContextT *ctx) {
    AppContextT *ac = ctx->shellCtx;

    WindowT *win = dvxCreateWindow(ac, appDescriptor.name, 100, 100, 320, 240, true);

    if (!win) {
        return -1;
    }

    win->onClose = onClose;
    return 0;
}
```

Add a Makefile target that mirrors the existing apps (see
`apps/kpunch/Makefile` for the pattern), drop a `.res` manifest next
to the source, and provide a 32x32 `icon32.bmp`. `make <app>` should
then produce `bin/apps/kpunch/<app>/<app>.app`.


## Testing Locally

After `make`, the app is deployed in-tree under `bin/apps/kpunch/`.
Launch the full system (`bin/dvx.exe`) and the Program Manager picks
up the new app automatically on the next boot.

To iterate quickly: rebuild the single app, restart DVX, and launch
it. The log at `bin/DVX.LOG` records load errors, missing
dependencies, and per-app crash diagnostics.


## Files

```
apps/kpunch/
  Makefile               top-level app build
  README.md              this file

  # C apps
  progman/
    progman.c            Program Manager
    dvxhelp.hcf          help-compiler config (system reference)
  clock/
    clock.c              digital clock (main-loop reference)
    clock.res
    icon32.bmp
  dvxdemo/
    dvxdemo.c            widget showcase
    dvxdemo.res
    icon32.bmp
    logo.bmp / new.bmp / open.bmp / sample.bmp / save.bmp
  cpanel/
    cpanel.c             Control Panel
    cpanel.res
    icon32.bmp
  dvxhelp/
    dvxhelp.c            help viewer
    dvxhelp.res
    help.dhs             source for the dvxhelp app's own help
    hlpformat.h          binary format shared with the compiler
    sample.dhs           small sample source
    icon32.bmp
    helpedit/            BASIC project: help editor
      helpedit.dbp
      helpedit.frm
      ICON32.BMP

  # BASIC apps
  iconed/
    iconed.dbp
    iconed.frm
    ICON32.BMP
  notepad/
    notepad.dbp
    notepad.frm
    ICON32.BMP
  imgview/
    imgview.dbp
    imgview.frm
    ICON32.BMP
  basdemo/
    basdemo.dbp
    basdemo.frm
    ICON32.BMP
  resedit/
    resedit.dbp
    resedit.frm
    ICON32.BMP

  dvxbasic/              see dvxbasic/README.md
    compiler/            lexer, parser, codegen, strip, obfuscate
    runtime/             VM + value system
    formrt/              form runtime (BASIC <-> DVX widgets)
    ide/                 IDE front end
    stub/                bascomp + basstub
    ...
```
