Now using -Wall -Werror (for real). All warnings fixed. Help system added.

This commit is contained in:
Scott Duensing 2026-04-07 18:28:39 -05:00
parent 0f5da09d1f
commit 2a641f42c3
80 changed files with 20540 additions and 9414 deletions

View file

@ -4,14 +4,14 @@ DJGPP_PREFIX = $(HOME)/djgpp/djgpp
DJGPP_LIBPATH = $(HOME)/claude/windriver/tools/lib
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I../core -I../core/platform -I../core/thirdparty -I../widgets -I../tasks -I../core/thirdparty -I../shell
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I../core -I../core/platform -I../core/thirdparty -I../widgets -I../tasks -I../core/thirdparty -I../shell
OBJDIR = ../obj/apps
BINDIR = ../bin/apps
DVXRES = ../bin/dvxres
# App definitions: each is a subdir with a single .c file
APPS = progman notepad clock dvxdemo cpanel imgview
APPS = progman notepad clock dvxdemo cpanel imgview dvxhelp
.PHONY: all clean $(APPS) dvxbasic
@ -26,6 +26,7 @@ progman: $(BINDIR)/progman/progman.app
notepad: $(BINDIR)/notepad/notepad.app
clock: $(BINDIR)/clock/clock.app
dvxdemo: $(BINDIR)/dvxdemo/dvxdemo.app
dvxhelp: $(BINDIR)/dvxhelp/dvxhelp.app
$(BINDIR)/cpanel/cpanel.app: $(OBJDIR)/cpanel.o cpanel/cpanel.res cpanel/icon32.bmp | $(BINDIR)/cpanel
$(DXE3GEN) -o $@ -E _appDescriptor -E _appMain -U $<
@ -71,6 +72,13 @@ $(OBJDIR)/clock.o: clock/clock.c | $(OBJDIR)
$(OBJDIR)/dvxdemo.o: dvxdemo/dvxdemo.c | $(OBJDIR)
$(CC) $(CFLAGS) -c -o $@ $<
$(BINDIR)/dvxhelp/dvxhelp.app: $(OBJDIR)/dvxhelp.o dvxhelp/dvxhelp.res dvxhelp/icon32.bmp | $(BINDIR)/dvxhelp
$(DXE3GEN) -o $@ -E _appDescriptor -E _appMain -U $<
$(DVXRES) build $@ dvxhelp/dvxhelp.res
$(OBJDIR)/dvxhelp.o: dvxhelp/dvxhelp.c dvxhelp/hlpformat.h | $(OBJDIR)
$(CC) $(CFLAGS) -c -o $@ $<
$(OBJDIR):
mkdir -p $(OBJDIR)
@ -92,6 +100,9 @@ $(BINDIR)/clock:
$(BINDIR)/dvxdemo:
mkdir -p $(BINDIR)/dvxdemo
$(BINDIR)/dvxhelp:
mkdir -p $(BINDIR)/dvxhelp
# Dependencies
$(OBJDIR)/imgview.o: imgview/imgview.c ../core/dvxApp.h ../core/dvxDialog.h ../core/dvxWidget.h ../core/dvxWm.h ../core/dvxVideo.h ../shell/shellApp.h
$(OBJDIR)/cpanel.o: cpanel/cpanel.c ../core/dvxApp.h ../core/dvxDialog.h ../core/dvxPrefs.h ../core/dvxWidget.h ../core/dvxWm.h ../core/platform/dvxPlatform.h ../shell/shellApp.h

View file

@ -955,7 +955,7 @@ static void scanThemes(void) {
memcpy(entry.name, ent->d_name, nameLen);
entry.name[nameLen] = '\0';
snprintf(entry.path, sizeof(entry.path), "%s/%s", THEME_DIR, entry.name);
snprintf(entry.path, sizeof(entry.path), "%s%c%s", THEME_DIR, DVX_PATH_SEP, entry.name);
arrput(sThemeEntries, entry);
}
@ -1010,7 +1010,7 @@ static void scanWallpapers(void) {
memcpy(entry.name, ent->d_name, nl);
entry.name[nl] = '\0';
snprintf(entry.path, sizeof(entry.path), "%s/%s", WPAPER_DIR, entry.name);
snprintf(entry.path, sizeof(entry.path), "%s%c%s", WPAPER_DIR, DVX_PATH_SEP, entry.name);
arrput(sWpaperEntries, entry);
}

View file

@ -12,7 +12,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I../../core -I../../core/platform -I../../widgets -I../../shell -I../../tasks -I../../core/thirdparty -I.
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I../../core -I../../core/platform -I../../widgets -I../../shell -I../../tasks -I../../core/thirdparty -I.
OBJDIR = ../../obj/dvxbasic
LIBSDIR = ../../bin/libs

View file

@ -5,6 +5,7 @@
#include "opcodes.h"
#include "thirdparty/stb_ds_wrap.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>

View file

@ -203,7 +203,6 @@ static const BasDebugVarT *findDebugVar(const char *name);
static void formatValue(const BasValueT *v, char *buf, int32_t bufSize);
static bool readDebugVar(const BasDebugVarT *dv, BasValueT *outVal);
static BasValueT *getDebugVarSlot(const BasDebugVarT *dv);
static bool writeDebugVar(const BasDebugVarT *dv, BasValueT newVal);
static void loadFrmFiles(BasFormRtT *rt);
static void onEvtDropdownChange(WidgetT *w);
static void onImmediateChange(WidgetT *w);
@ -329,7 +328,7 @@ typedef struct {
int32_t fileIdx; // project file index
int32_t codeLine; // line within file's code section (1-based)
int32_t procIdx; // procedure index at time of toggle (-1 = general)
char procName[64]; // procedure name at time of toggle
char procName[BAS_MAX_PROC_NAME * 2]; // "obj.evt" combined name
} IdeBreakpointT;
static IdeDebugStateE sDbgState = DBG_IDLE;
@ -1072,45 +1071,6 @@ static int32_t localToConcatLine(int32_t editorLine) {
}
// ============================================================
// concatToLocalLine -- convert concatenated source line to editor-local line
// ============================================================
// Convert a full-source line number back to an editor-local line number.
// Reverses the file offset, BEGINFORM offset, and procedure offset so
// the line matches what the user sees in the editor.
static int32_t concatToLocalLine(int32_t concatLine) {
int32_t fileLine = concatLine;
// Strip multi-file offset and BEGINFORM offset
if (sProject.sourceMapCount > 0) {
int32_t fileIdx = -1;
int32_t localLine = concatLine;
if (prjMapLine(&sProject, concatLine, &fileIdx, &localLine)) {
fileLine = localLine;
// For .frm files, subtract the BEGINFORM line
if (fileIdx >= 0 && fileIdx < sProject.fileCount &&
sProject.files[fileIdx].isForm) {
fileLine--;
}
}
}
// Strip procedure offset to get editor-local line
if (sCurProcIdx >= 0 && sCurProcIdx < (int32_t)arrlen(sProcTable)) {
int32_t procStart = sProcTable[sCurProcIdx].lineNum;
if (fileLine >= procStart) {
return fileLine - procStart + 1;
}
}
return fileLine;
}
// ============================================================
// debugLineDecorator -- highlight breakpoints and current debug line
// ============================================================
@ -1860,7 +1820,6 @@ static void runModule(BasModuleT *mod) {
// Hide designer windows while the program runs.
// Keep the code window visible if debugging (breakpoints or step-into).
bool debugging = sDbgEnabled;
bool hadFormWin = sFormWin && sFormWin->visible;
bool hadToolbox = sToolboxWin && sToolboxWin->visible;
bool hadProps = sPropsWin && sPropsWin->visible;
@ -3882,7 +3841,6 @@ static bool findInProject(const char *needle, bool caseSensitive) {
// Start from the active file, searching from after the current selection
int32_t startFile = sProject.activeFileIdx >= 0 ? sProject.activeFileIdx : 0;
int32_t startPos = 0;
// If the editor is open on the current file, try the current proc
// first (no wrap — returns false if no more matches ahead).
@ -5447,8 +5405,6 @@ static void dsgnPasteControl(void) {
break;
}
const char *lineStart = line;
while (*line == ' ' || *line == '\t') {
line++;
}
@ -6366,7 +6322,7 @@ static void showImmediateWindow(void) {
#define MAX_BP_DISPLAY 64
static char sBpFiles[MAX_BP_DISPLAY][DVX_MAX_PATH];
static char sBpProcs[MAX_BP_DISPLAY][64];
static char sBpProcs[MAX_BP_DISPLAY][BAS_MAX_PROC_NAME * 2];
static char sBpLines[MAX_BP_DISPLAY][12];
static const char *sBpCells[MAX_BP_DISPLAY * 3];
@ -6507,7 +6463,7 @@ static void updateBreakpointWindow(void) {
snprintf(sBpProcs[i], sizeof(sBpProcs[i]), "%s", sBreakpoints[i].procName);
// Line number
snprintf(sBpLines[i], sizeof(sBpLines[i]), "%d", sBreakpoints[i].codeLine);
snprintf(sBpLines[i], sizeof(sBpLines[i]), "%d", (int)sBreakpoints[i].codeLine);
sBpCells[i * 3] = sBpFiles[i];
sBpCells[i * 3 + 1] = sBpProcs[i];
@ -6605,8 +6561,8 @@ static void formatValue(const BasValueT *v, char *buf, int32_t bufSize) {
case BAS_TYPE_DOUBLE: snprintf(buf, bufSize, "%.10g", v->dblVal); break;
case BAS_TYPE_BOOLEAN: snprintf(buf, bufSize, "%s", v->boolVal ? "True" : "False"); break;
case BAS_TYPE_STRING: {
if (v->strVal && v->strVal->data) {
snprintf(buf, bufSize, "\"%.*s\"", bufSize - 3, v->strVal->data);
if (v->strVal) {
snprintf(buf, bufSize, "\"%.*s\"", (int)(bufSize - 3), v->strVal->data);
} else {
snprintf(buf, bufSize, "\"\"");
}
@ -6872,7 +6828,7 @@ static void updateCallStackWindow(void) {
}
snprintf(sCallNames[rowCount], BAS_MAX_PROC_NAME, "%s", name);
snprintf(sCallLines[rowCount], 16, "");
sCallLines[rowCount][0] = '\0';
sCallCells[rowCount * 2 + 0] = sCallNames[rowCount];
sCallCells[rowCount * 2 + 1] = sCallLines[rowCount];
rowCount++;
@ -7106,19 +7062,6 @@ static BasValueT *getDebugVarSlot(const BasDebugVarT *dv) {
}
static bool writeDebugVar(const BasDebugVarT *dv, BasValueT newVal) {
BasValueT *slot = getDebugVarSlot(dv);
if (!slot) {
return false;
}
basValRelease(slot);
*slot = basValCopy(newVal);
return true;
}
// findDebugVar -- find a debug variable by name, respecting scope
static const BasDebugVarT *findDebugVar(const char *name) {
if (!sDbgModule || !sDbgModule->debugVars) {
@ -7448,7 +7391,7 @@ static void updateWatchWindow(void) {
snprintf(sWatchValBuf[i], 256, "<error>");
}
} else {
snprintf(sWatchValBuf[i], 256, "");
sWatchValBuf[i][0] = '\0';
}
sWatchCells[i * 2 + 0] = sWatchExprBuf[i];

View file

@ -117,7 +117,7 @@ static void applyFields(void) {
}
}
snprintf(autoName, DSGN_MAX_NAME, "mnuSep%d", sepNum);
snprintf(autoName, DSGN_MAX_NAME, "mnuSep%d", (int)sepNum);
} else {
// Normal item: strip & and non-alphanumeric, prefix "mnu"
int32_t p = 0;

View file

@ -279,7 +279,7 @@ void prjNew(PrjStateT *prj, const char *name, const char *directory, PrefsHandle
prjInit(prj);
snprintf(prj->name, sizeof(prj->name), "%s", name);
snprintf(prj->projectDir, sizeof(prj->projectDir), "%s", directory);
snprintf(prj->projectPath, sizeof(prj->projectPath), "%s/%s.dbp", directory, name);
snprintf(prj->projectPath, sizeof(prj->projectPath), "%s%c%s.dbp", directory, DVX_PATH_SEP, name);
prj->dirty = true;
// Apply defaults from preferences
@ -416,7 +416,7 @@ void prjFullPath(const PrjStateT *prj, int32_t fileIdx, char *outPath, int32_t o
return;
}
snprintf(outPath, outSize, "%s/%s", prj->projectDir, prj->files[fileIdx].path);
snprintf(outPath, outSize, "%s%c%s", prj->projectDir, DVX_PATH_SEP, prj->files[fileIdx].path);
}
@ -633,7 +633,7 @@ static void ppdOnOk(WidgetT *w) {
// Validate icon path if set
if (sPpd.iconPath[0] && sPpd.prj) {
char fullPath[DVX_MAX_PATH * 2];
snprintf(fullPath, sizeof(fullPath), "%s/%s", sPpd.prj->projectDir, sPpd.iconPath);
snprintf(fullPath, sizeof(fullPath), "%s%c%s", sPpd.prj->projectDir, DVX_PATH_SEP, sPpd.iconPath);
if (!validateIcon(fullPath, true)) {
return;
@ -686,7 +686,7 @@ static void ppdLoadIconPreview(void) {
const char *relPath = sPpd.iconPath;
char fullPath[DVX_MAX_PATH * 2];
snprintf(fullPath, sizeof(fullPath), "%s/%s", sPpd.prj->projectDir, relPath);
snprintf(fullPath, sizeof(fullPath), "%s%c%s", sPpd.prj->projectDir, DVX_PATH_SEP, relPath);
if (!validateIcon(fullPath, true)) {
sPpd.iconPath[0] = '\0';
@ -750,7 +750,7 @@ static void ppdOnBrowseIcon(WidgetT *w) {
// Check if destination already exists
char destPath[DVX_MAX_PATH * 2];
snprintf(destPath, sizeof(destPath), "%s/%s", sPpd.prj->projectDir, fname);
snprintf(destPath, sizeof(destPath), "%s%c%s", sPpd.prj->projectDir, DVX_PATH_SEP, fname);
FILE *existing = fopen(destPath, "rb");
@ -875,7 +875,7 @@ bool prjPropertiesDialog(AppContextT *ctx, PrjStateT *prj, const char *appPath)
// Use the cached form object name, fall back to filename
const char *name = prj->files[i].formName;
char fallback[PRJ_MAX_NAME];
char fallback[DVX_MAX_PATH];
if (!name[0]) {
snprintf(fallback, sizeof(fallback), "%s", prj->files[i].path);

View file

@ -107,7 +107,7 @@ static void resolveDbPath(const char *dbName, char *out, int32_t outSize) {
// Resolve relative to project directory
if (sDs && sDs->projectDir && sDs->projectDir[0]) {
snprintf(out, outSize, "%s/%s", sDs->projectDir, dbName);
snprintf(out, outSize, "%s%c%s", sDs->projectDir, DVX_PATH_SEP, dbName);
} else {
snprintf(out, outSize, "%s", dbName);
}
@ -549,7 +549,7 @@ static void onPropDblClick(WidgetT *w) {
}
if (chosenIdx == 0) {
snprintf(newValue, sizeof(newValue), "");
newValue[0] = '\0';
} else {
snprintf(newValue, sizeof(newValue), "%s", dataNames[chosenIdx]);
}
@ -611,7 +611,7 @@ static void onPropDblClick(WidgetT *w) {
}
if (chosenIdx == 0) {
snprintf(newValue, sizeof(newValue), "");
newValue[0] = '\0';
} else {
snprintf(newValue, sizeof(newValue), "%s", fieldNames[chosenIdx - 1]);
}
@ -669,7 +669,7 @@ static void onPropDblClick(WidgetT *w) {
}
if (chosenIdx == 0) {
snprintf(newValue, sizeof(newValue), "");
newValue[0] = '\0';
} else {
snprintf(newValue, sizeof(newValue), "%s", tableNames[chosenIdx - 1]);
}

View file

@ -16,6 +16,7 @@
#include "values.h"
#include "dvxTypes.h"
#include "dvxPlatform.h"
#include <stdint.h>
#include <stdbool.h>

1406
apps/dvxhelp/dvxhelp.c Normal file

File diff suppressed because it is too large Load diff

5
apps/dvxhelp/dvxhelp.res Normal file
View file

@ -0,0 +1,5 @@
# dvxhelp.res -- Resource manifest for DVX Help Viewer
icon32 icon dvxhelp/icon32.bmp
name text "DVX Help"
author text "DVX Project"
description text "Help file viewer"

157
apps/dvxhelp/hlpformat.h Normal file
View file

@ -0,0 +1,157 @@
// hlpformat.h -- DVX Help binary file format structures
//
// Shared between the host-side help compiler and the DVX help viewer app.
#ifndef HLPFORMAT_H
#define HLPFORMAT_H
#include <stdint.h>
#include <stdbool.h>
// ---------------------------------------------------------------------------
// File magic and version
// ---------------------------------------------------------------------------
#define HLP_MAGIC 0x484C5044 // "HLPD" little-endian
#define HLP_VERSION 1
// ---------------------------------------------------------------------------
// Record types (HlpRecordHdrT.type)
// ---------------------------------------------------------------------------
#define HLP_REC_TEXT 0x01
#define HLP_REC_HEADING1 0x02
#define HLP_REC_HEADING2 0x03
#define HLP_REC_HEADING3 0x04
#define HLP_REC_IMAGE 0x05
#define HLP_REC_LINK 0x06
#define HLP_REC_LIST_ITEM 0x07
#define HLP_REC_TABLE 0x08
#define HLP_REC_HRULE 0x09
#define HLP_REC_NOTE 0x0A
#define HLP_REC_CODE 0x0B
#define HLP_REC_END 0xFF
// ---------------------------------------------------------------------------
// Note flags (HlpRecordHdrT.flags when type == HLP_REC_NOTE)
// ---------------------------------------------------------------------------
#define HLP_NOTE_INFO 0x00
#define HLP_NOTE_TIP 0x01
#define HLP_NOTE_WARNING 0x02
// ---------------------------------------------------------------------------
// TOC entry flags
// ---------------------------------------------------------------------------
#define HLP_TOC_EXPANDED 0x01
// ---------------------------------------------------------------------------
// File header (64 bytes, stored at EOF)
// ---------------------------------------------------------------------------
typedef struct {
uint32_t magic; // HLP_MAGIC
uint32_t version; // HLP_VERSION
uint32_t topicCount;
uint32_t topicDirOffset; // absolute file offset
uint32_t tocOffset;
uint32_t tocCount;
uint32_t indexOffset;
uint32_t indexCount;
uint32_t searchOffset;
uint32_t searchSize;
uint32_t stringTableOffset;
uint32_t stringTableSize;
uint32_t imagePoolOffset;
uint32_t imagePoolSize;
uint32_t defaultTopicStr; // string table offset of default topic ID
uint32_t wrapWidth; // column width text was pre-wrapped at
} HlpHeaderT;
// ---------------------------------------------------------------------------
// Topic directory entry (20 bytes)
// ---------------------------------------------------------------------------
typedef struct {
uint32_t topicIdStr; // string table offset
uint32_t titleStr; // string table offset
uint32_t contentOffset; // absolute file offset
uint32_t contentSize;
uint32_t reserved;
} HlpTopicDirT;
// ---------------------------------------------------------------------------
// Content record header (4 bytes)
// ---------------------------------------------------------------------------
typedef struct {
uint8_t type;
uint8_t flags;
uint16_t length; // payload length (excluding this header)
} HlpRecordHdrT;
// ---------------------------------------------------------------------------
// Image reference (8 bytes, payload of HLP_REC_IMAGE)
// ---------------------------------------------------------------------------
typedef struct {
uint32_t imageOffset; // offset within image pool
uint32_t imageSize; // BMP data size
} HlpImageRefT;
// ---------------------------------------------------------------------------
// TOC entry (8 bytes)
// ---------------------------------------------------------------------------
typedef struct {
uint32_t titleStr; // string table offset
uint16_t topicIdx; // index into topic directory (0xFFFF = no topic)
uint8_t depth; // nesting depth (0 = root)
uint8_t flags; // HLP_TOC_EXPANDED
} HlpTocEntryT;
// ---------------------------------------------------------------------------
// Keyword index entry (8 bytes)
// ---------------------------------------------------------------------------
typedef struct {
uint32_t keywordStr; // string table offset
uint16_t topicIdx; // index into topic directory
uint16_t reserved;
} HlpIndexEntryT;
// ---------------------------------------------------------------------------
// Search index -- trigram entry (8 bytes)
// ---------------------------------------------------------------------------
typedef struct {
uint8_t trigram[3];
uint8_t postingCount;
uint32_t postingOffset; // byte offset within search section to uint16_t[] posting list
} HlpTrigramEntryT;
// ---------------------------------------------------------------------------
// Search section header
// ---------------------------------------------------------------------------
typedef struct {
uint32_t trigramCount;
// followed by HlpTrigramEntryT[trigramCount]
// followed by uint16_t posting lists
} HlpSearchHeaderT;
#endif // HLPFORMAT_H

BIN
apps/dvxhelp/icon32.bmp (Stored with Git LFS) Normal file

Binary file not shown.

155
apps/dvxhelp/sample.dvxhelp Normal file
View file

@ -0,0 +1,155 @@
.topic intro
.title Welcome to DVX
.toc 0 Welcome to DVX
.default
.index DVX
.index Introduction
.index Getting Started
.h1 Welcome to DVX
DVX is a graphical user interface environment for DOS, designed
for 486-class hardware and above. It provides a windowing system
with a Motif-inspired visual style, cooperative multitasking,
and a widget-based application framework.
DVX features include:
.list
.item A window manager with drag, resize, and minimize support
.item Over 25 built-in widget types including buttons, lists, and trees
.item Dynamic application loading via DXE3 modules
.item Theme support with customizable color schemes
.item VESA VBE 2.0+ linear framebuffer rendering
.endlist
.link overview See also: System Overview
.hr
.note tip
Press F1 from any DVX application to open context-sensitive help.
.endnote
.topic overview
.title System Overview
.toc 0 System Overview
.index Architecture
.index Layers
.h1 System Overview
DVX is built as a five-layer architecture, with each layer
providing services to the layer above it.
.h2 Video Layer
The video layer (dvxVideo) handles VESA VBE initialization,
linear framebuffer mapping, backbuffer allocation, and pixel
format detection. It supports 8-bit, 16-bit, and 32-bit color
depths.
.h2 Drawing Layer
The drawing layer (dvxDraw) provides primitive rendering
operations: filled rectangles, beveled borders, text rendering,
bitmap blitting, and clipped drawing.
.h2 Compositor
The compositor (dvxComp) manages a dirty rectangle list. Only
regions that have changed since the last frame are flushed from
the system RAM backbuffer to the video card's linear framebuffer.
.h2 Window Manager
The window manager (dvxWm) handles the window stack, chrome
rendering (title bars, borders, close buttons), drag and resize
interaction, focus management, and menu bars.
.h2 Application Layer
The application layer (dvxApp) ties everything together with
the event loop, mouse and keyboard input, accelerator tables,
and the public API used by applications.
.link widgets See also: Widget System
.topic widgets
.title Widget System
.toc 0 Widget System
.index Widgets
.index Controls
.h1 Widget System
DVX provides a rich set of widgets (controls) for building
application user interfaces. Widgets are loaded as DXE3 plugin
modules at startup.
.h2 Layout Widgets
.list
.item VBox -- Vertical box layout (stacks children vertically)
.item HBox -- Horizontal box layout (stacks children horizontally)
.item Frame -- Labeled group box with border
.item ScrollPane -- Scrollable container for oversized content
.item Splitter -- Resizable split between two panes
.item TabControl -- Tabbed container
.endlist
.h2 Input Widgets
.list
.item Button -- Push button with text label
.item TextInput -- Single-line text entry field
.item TextArea -- Multi-line text editor with syntax highlighting
.item Checkbox -- Boolean toggle with label
.item Radio -- Mutually exclusive option selector
.item Dropdown -- Drop-down selection list
.item ComboBox -- Editable dropdown with text entry
.item Slider -- Horizontal or vertical value slider
.item Spinner -- Numeric up/down control
.endlist
.h2 Display Widgets
.list
.item Label -- Single-line text display
.item Image -- Bitmap image display
.item ProgressBar -- Visual progress indicator
.item Canvas -- Custom drawing surface
.item Separator -- Horizontal or vertical divider line
.endlist
.h2 Data Widgets
.list
.item ListBox -- Scrollable list of text items
.item ListView -- Multi-column sortable list with headers
.item TreeView -- Hierarchical tree with expand/collapse
.endlist
.topic keyboard
.title Keyboard Shortcuts
.toc 0 Keyboard Shortcuts
.index Keyboard
.index Shortcuts
.index Hotkeys
.h1 Keyboard Shortcuts
The following keyboard shortcuts are available system-wide
in DVX:
.table
Shortcut Action
-------- ------
Alt+F4 Close active window
F10 Activate menu bar
Ctrl+Esc Open task manager
Tab Move focus to next widget
Shift+Tab Move focus to previous widget
Enter Activate focused button
Escape Close dialog or cancel operation
.endtable

View file

@ -418,7 +418,7 @@ static void scanAppsDirRecurse(const char *dirPath) {
}
char fullPath[MAX_PATH_LEN];
snprintf(fullPath, sizeof(fullPath), "%s/%s", dirPath, ent->d_name);
snprintf(fullPath, sizeof(fullPath), "%s%c%s", dirPath, DVX_PATH_SEP, ent->d_name);
// Check if this is a directory -- recurse into it
struct stat st;

View file

@ -7,7 +7,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I. -Iplatform -I../tasks -Ithirdparty
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I. -Iplatform -I../tasks -Ithirdparty
OBJDIR = ../obj/core
LIBSDIR = ../bin/libs

View file

@ -2412,6 +2412,15 @@ static void pollKeyboard(AppContextT *ctx) {
continue;
}
// F1 -- system-wide help
if (ascii == 0 && scancode == 0x3B && !(shiftFlags & (KEY_MOD_CTRL | KEY_MOD_ALT | KEY_MOD_SHIFT))) {
if (ctx->onF1) {
ctx->onF1(ctx->f1Ctx);
}
continue;
}
// F10 -- activate menu bar
if (ascii == 0 && scancode == 0x44) {
if (ctx->stack.focusedIdx >= 0) {

View file

@ -15,6 +15,7 @@
#include "dvxCursor.h"
#include "dvxTypes.h"
#include "dvxPlatform.h"
#include "dvxVideo.h"
#include "dvxDraw.h"
#include "dvxComp.h"
@ -81,6 +82,8 @@ typedef struct AppContextT {
WindowT *modalWindow; // if non-NULL, only this window receives input
void (*onCtrlEsc)(void *ctx); // system-wide Ctrl+Esc handler (e.g. task manager)
void *ctrlEscCtx;
void (*onF1)(void *ctx); // system-wide F1 handler (context-sensitive help)
void *f1Ctx;
void (*onTitleChange)(void *ctx); // called when any window title changes
void *titleChangeCtx;
int32_t currentAppId; // set by shell before calling app code (0 = shell)

View file

@ -1231,7 +1231,7 @@ static void fdLoadDir(void) {
// Build full path to stat
char fullPath[FD_MAX_PATH * 2];
snprintf(fullPath, sizeof(fullPath), "%s/%s", sFd.curDir, ent->d_name);
snprintf(fullPath, sizeof(fullPath), "%s%c%s", sFd.curDir, DVX_PATH_SEP, ent->d_name);
struct stat st;
@ -1352,7 +1352,7 @@ static void fdNavigate(const char *path) {
resolved[FD_MAX_PATH - 1] = '\0';
} else {
char tmp[FD_MAX_PATH * 2];
snprintf(tmp, sizeof(tmp), "%s/%s", sFd.curDir, path);
snprintf(tmp, sizeof(tmp), "%s%c%s", sFd.curDir, DVX_PATH_SEP, path);
strncpy(resolved, tmp, FD_MAX_PATH - 1);
resolved[FD_MAX_PATH - 1] = '\0';
}
@ -1411,7 +1411,7 @@ static bool fdAcceptFile(const char *name) {
}
char fullPath[FD_MAX_PATH * 2];
snprintf(fullPath, sizeof(fullPath), "%s/%s", sFd.curDir, name);
snprintf(fullPath, sizeof(fullPath), "%s%c%s", sFd.curDir, DVX_PATH_SEP, name);
struct stat st;
bool exists = (stat(fullPath, &st) == 0 && S_ISREG(st.st_mode));
@ -1551,7 +1551,7 @@ static void fdOnOk(WidgetT *w) {
// If user typed a directory path, navigate there
char testPath[FD_MAX_PATH * 2];
snprintf(testPath, sizeof(testPath), "%s/%s", sFd.curDir, name);
snprintf(testPath, sizeof(testPath), "%s%c%s", sFd.curDir, DVX_PATH_SEP, name);
struct stat st;
@ -1734,7 +1734,7 @@ bool dvxFileDialog(AppContextT *ctx, const char *title, int32_t flags, const cha
if (name && name[0]) {
char tmp[FD_MAX_PATH * 2];
snprintf(tmp, sizeof(tmp), "%s/%s", sFd.curDir, name);
snprintf(tmp, sizeof(tmp), "%s%c%s", sFd.curDir, DVX_PATH_SEP, name);
strncpy(sFd.outPath, tmp, FD_MAX_PATH - 1);
sFd.outPath[FD_MAX_PATH - 1] = '\0';

View file

@ -18,11 +18,7 @@
#include <stdint.h>
// Fallback for the native dvxres tool, which includes this header
// without dvxTypes.h. The canonical definition is in dvxTypes.h.
#ifndef DVX_MAX_PATH
#define DVX_MAX_PATH 260
#endif
#include "dvxPlatform.h"
// Resource type IDs
#define DVX_RES_ICON 1 // image data (BMP icon: 16x16, 32x32, etc.)

View file

@ -12,14 +12,6 @@
#include <stdbool.h>
// ============================================================
// Path limits
// ============================================================
//
// Maximum file path length. 260 matches DOS MAX_PATH. Future
// platforms (Linux, Windows) should increase this.
#define DVX_MAX_PATH 260
// ============================================================
// Pixel format descriptor
// ============================================================

View file

@ -26,6 +26,9 @@
#include <setjmp.h>
// Maximum file path length. 260 matches DOS MAX_PATH.
#define DVX_MAX_PATH 260
// ============================================================
// Keyboard event
// ============================================================
@ -262,6 +265,10 @@ void platformVideoFreeBuffers(DisplayT *d);
// accepts either.
char *platformPathDirEnd(const char *path);
// The platform's native directory separator character.
// '/' on DJGPP (which accepts both '/' and '\\').
#define DVX_PATH_SEP '/'
// Return the platform's native line ending string.
// "\r\n" on DOS.
const char *platformLineEnding(void);

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

155
docs/dvx_help_sample.html Normal file
View file

@ -0,0 +1,155 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Welcome to DVX</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="#intro">Welcome to DVX</a></li>
<li><a href="#overview">System Overview</a></li>
<li><a href="#widgets">Widget System</a></li>
<li><a href="#keyboard">Keyboard Shortcuts</a></li>
</ul>
<h3>Index</h3>
<ul>
<li><a href="#intro">DVX</a></li>
<li><a href="#intro">Introduction</a></li>
<li><a href="#intro">Getting Started</a></li>
<li><a href="#overview">Architecture</a></li>
<li><a href="#overview">Layers</a></li>
<li><a href="#widgets">Widgets</a></li>
<li><a href="#widgets">Controls</a></li>
<li><a href="#keyboard">Keyboard</a></li>
<li><a href="#keyboard">Shortcuts</a></li>
<li><a href="#keyboard">Hotkeys</a></li>
</ul>
</nav>
<main>
<div class="topic" id="intro">
<h1>Welcome to DVX</h1>
<h2>Welcome to DVX</h2>
<p>DVX is a graphical user interface environment for DOS, designed for
486-class hardware and above. It provides a windowing system with a
Motif-inspired visual style, cooperative multitasking, and a widget-based
application framework.</p>
<p>DVX features include:</p>
<ul>
<li>A window manager with drag, resize, and minimize support</li>
<li>Over 25 built-in widget types including buttons, lists, and trees</li>
<li>Dynamic application loading via DXE3 modules</li>
<li>Theme support with customizable color schemes</li>
</ul>
<p>VESA VBE 2.0+ linear framebuffer rendering</p>
<p><a href="#overview">See also: System Overview</a></p>
<hr>
<blockquote><strong>Tip:</strong> Press F1 from any DVX application to open context-sensitive help.</blockquote>
</div>
<div class="topic" id="overview">
<h1>System Overview</h1>
<h2>System Overview</h2>
<p>DVX is built as a five-layer architecture, with each layer providing
services to the layer above it.</p>
<h3>Video Layer</h3>
<p>The video layer (dvxVideo) handles VESA VBE initialization, linear
framebuffer mapping, backbuffer allocation, and pixel format detection. It
supports 8-bit, 16-bit, and 32-bit color depths.</p>
<h3>Drawing Layer</h3>
<p>The drawing layer (dvxDraw) provides primitive rendering operations: filled
rectangles, beveled borders, text rendering, bitmap blitting, and clipped
drawing.</p>
<h3>Compositor</h3>
<p>The compositor (dvxComp) manages a dirty rectangle list. Only regions that
have changed since the last frame are flushed from the system RAM backbuffer
to the video card's linear framebuffer.</p>
<h3>Window Manager</h3>
<p>The window manager (dvxWm) handles the window stack, chrome rendering (title
bars, borders, close buttons), drag and resize interaction, focus
management, and menu bars.</p>
<h3>Application Layer</h3>
<p>The application layer (dvxApp) ties everything together with the event loop,
mouse and keyboard input, accelerator tables, and the public API used by
applications.</p>
<p><a href="#widgets">See also: Widget System</a></p>
</div>
<div class="topic" id="widgets">
<h1>Widget System</h1>
<h2>Widget System</h2>
<p>DVX provides a rich set of widgets (controls) for building application user
interfaces. Widgets are loaded as DXE3 plugin modules at startup.</p>
<h3>Layout Widgets</h3>
<ul>
<li>VBox -- Vertical box layout (stacks children vertically)</li>
<li>HBox -- Horizontal box layout (stacks children horizontally)</li>
<li>Frame -- Labeled group box with border</li>
<li>ScrollPane -- Scrollable container for oversized content</li>
<li>Splitter -- Resizable split between two panes</li>
</ul>
<p>TabControl -- Tabbed container</p>
<h3>Input Widgets</h3>
<ul>
<li>Button -- Push button with text label</li>
<li>TextInput -- Single-line text entry field</li>
<li>TextArea -- Multi-line text editor with syntax highlighting</li>
<li>Checkbox -- Boolean toggle with label</li>
<li>Radio -- Mutually exclusive option selector</li>
<li>Dropdown -- Drop-down selection list</li>
<li>ComboBox -- Editable dropdown with text entry</li>
<li>Slider -- Horizontal or vertical value slider</li>
</ul>
<p>Spinner -- Numeric up/down control</p>
<h3>Display Widgets</h3>
<ul>
<li>Label -- Single-line text display</li>
<li>Image -- Bitmap image display</li>
<li>ProgressBar -- Visual progress indicator</li>
<li>Canvas -- Custom drawing surface</li>
</ul>
<p>Separator -- Horizontal or vertical divider line</p>
<h3>Data Widgets</h3>
<ul>
<li>ListBox -- Scrollable list of text items</li>
<li>ListView -- Multi-column sortable list with headers</li>
</ul>
<p>TreeView -- Hierarchical tree with expand/collapse</p>
</div>
<div class="topic" id="keyboard">
<h1>Keyboard Shortcuts</h1>
<h2>Keyboard Shortcuts</h2>
<p>The following keyboard shortcuts are available system-wide in DVX:</p>
<pre> Shortcut Action
-------- ------
Alt+F4 Close active window
F10 Activate menu bar
Ctrl+Esc Open task manager
Tab Move focus to next widget
Shift+Tab Move focus to previous widget
Enter Activate focused button
Escape Close dialog or cancel operation</pre>
</div>
</main>
</body>
</html>

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,776 @@
.topic arch.overview
.title DVX Architecture Overview
.toc 0 System Overview
.default
.index DVX
.index Architecture
.index DJGPP
.index DPMI
.h1 DVX Architecture Overview
DOS Visual eXecutive -- A Windowing GUI for DJGPP/DPMI
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.
.h2 Key Design Constraints
.list
.item VESA VBE 2.0+ LFB only -- no bank switching. If the hardware cannot provide a linear framebuffer, initialization fails.
.item 486 baseline -- all hot paths are written to be fast on a 486, with Pentium-specific paths where the gain is significant.
.item Single-tasking cooperative model -- applications yield the CPU via tsYield(); there is no preemptive scheduler.
.item 86Box is the trusted reference platform for testing. DOSBox-X is not used; any bugs observed are treated as DVX bugs.
.item No external font or cursor files -- all bitmaps are compiled in as static const data.
.endlist
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.
.h2 Contents
.list
.item .link arch.overview System Overview
.item .link arch.layers Five-Layer Architecture
.item .link arch.pipeline Display Pipeline
.item .link arch.windows Window System
.item .link arch.widgets Widget System
.item .link arch.dxe DXE Module System
.item .link arch.events Event Model
.item .link arch.fonts Font System
.item .link arch.colors Color System
.item .link arch.platform Platform Layer
.item .link arch.build Build System
.endlist
.topic arch.layers
.title Five-Layer Architecture
.toc 0 Five-Layer Architecture
.index Layers
.index dvxVideo
.index dvxDraw
.index dvxComp
.index dvxWm
.index dvxApp
.h1 Five-Layer Architecture
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.
.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 (dvxPlatform.h) | | dvxPlatformDos.c
| | OS-specific: video, input, asm spans | |
| +------------------------------------------+ |
| |
| +------------------------------------------+ |
| | Shared Types (dvxTypes.h) | |
| | DisplayT, WindowT, RectT, ColorSchemeT | |
| +------------------------------------------+ |
==================================================
.endcode
.h2 Layer Summary
.table
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.
.endtable
.topic arch.pipeline
.title Display Pipeline
.toc 0 Display Pipeline
.index Display Pipeline
.index Backbuffer
.index Linear Framebuffer
.index LFB
.index Dirty Rects
.index Double Buffer
.index Compositing
.h1 Display Pipeline
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.
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.
.h2 Per-Frame Compositing Pipeline
.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)
.endcode
.h2 Key Data Structures
.index DisplayT
.index BlitOpsT
.index DirtyListT
DisplayT -- Central display context: width, height, pitch, pixel format, LFB pointer, backbuffer pointer, palette, clip rectangle. Passed by pointer through every layer -- no globals.
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.
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.
.h2 Why This Works on a 486
.list
.item A full 640x480x32bpp frame is 1.2 MB -- far too much to flush every frame over a slow PCI bus.
.item A typical dirty region during normal interaction (typing, menu open) is a few KB.
.item Merging overlapping dirty rects into larger rects reduces per-rect overhead and improves bus utilization.
.item Per-window content buffers persist across frames, so windows don't repaint on expose -- only when their own content changes.
.endlist
.topic arch.windows
.title Window System
.toc 0 Window System
.index Window
.index WindowT
.index Z-Order
.index Chrome
.index Hit Testing
.index Menu System
.index Minimized Windows
.h1 Window System
.h2 WindowT Structure
Each WindowT is the central object of the window manager. Key fields:
.table
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.
.endtable
.h2 Window Stack (Z-Order)
.index Window Stack
WindowStackT is an array of WindowT* ordered front-to-back: index count-1 is the topmost window. This allows:
.list
.item Back-to-front iteration for painting (painter's algorithm).
.item Front-to-back iteration for hit testing (first hit wins).
.item Reordering by pointer swap (no copying of large WindowT structs).
.endlist
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.
.h2 Chrome Layout
.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 |
+-------------------------------------------+
.endcode
Chrome constants are compile-time defines:
.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
.endcode
.h2 Hit Test Regions
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).
.h2 Menu System
.index Menus
.index Submenus
Menus use fixed-size arrays with inline char buffers (no heap strings). Up to 8 menus per bar, items dynamically allocated. 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.
.h2 Minimized Windows
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.
.topic arch.widgets
.title Widget System
.toc 0 Widget System
.index Widgets
.index WidgetT
.index WidgetClassT
.index Layout Engine
.index Widget API
.h1 Widget System
The widget system (dvxWidget.h) is a retained-mode toolkit layered on top of the window manager. Widgets form a tree rooted at a per-window VBox container.
.h2 WidgetT Base Structure
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->data (opaque void*).
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.
.h2 Layout Engine
.index Layout
.index Flexbox
Two-pass flexbox-like algorithm:
.list
.item Bottom-up (calcMinSize) -- compute minimum sizes for every widget, starting from leaves.
.item Top-down (layout) -- allocate space within available bounds, distributing extra space according to weight values (0 = fixed, 100 = normal stretch).
.endlist
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).
.h2 Widget Class Dispatch (WidgetClassT)
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.
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).
.h3 Class Flags
.table
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)
.endtable
.h2 Available Widget Types
Each widget is a separate .wgt DXE module. 29 widget types are included:
.table
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)
.endtable
.h2 Widget API Registry
Each widget DXE registers a small API struct under a name during wgtRegister(). Callers retrieve it via wgtGetApi("button") 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.
.h2 Widget Interface Descriptors (WgtIfaceT)
.index WgtIfaceT
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).
.topic arch.dxe
.title DXE Module System
.toc 0 DXE Module System
.index DXE
.index DXE3
.index Modules
.index Dynamic Loading
.h1 DXE Module System
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.
.h2 Module Types
.table
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
.endtable
.h2 Boot Sequence
.index Boot Sequence
.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() -> tsYield() -> shellReapApps()
.endcode
.h2 Application Lifecycle
Two kinds of DXE apps:
.h3 Callback-only (hasMainLoop = false)
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.
.h3 Main-loop (hasMainLoop = true)
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.
.h2 Crash Recovery
.index Crash Recovery
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.
.h2 Per-App Memory Tracking
.index Memory Tracking
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.
.topic arch.events
.title Event Model
.toc 0 Event Model
.index Events
.index Input
.index Mouse
.index Keyboard
.index Polling
.index Cooperative
.h1 Event Model
DVX uses a cooperative polling model. The main loop (dvxRun / dvxUpdate) runs this cycle each frame:
.list
.item Poll mouse -- platformMousePoll() returns position and button bitmask. Compare with previous frame for press/release edge detection.
.item Poll keyboard -- platformKeyboardRead() returns ASCII + scancode. Non-blocking; returns false if buffer is empty.
.item 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.
.item Compositor pass -- merge dirty rects, composite, flush to LFB.
.item Yield -- platformYield() or idle callback.
.endlist
.h2 Event Dispatch Chain
.index Event Dispatch
.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.)
.endcode
.h2 Accelerator Tables
.index Accelerator Tables
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.
.h2 Mouse Cursor
.index Cursor
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.
.h2 Double-Click Detection
.index Double-Click
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.
.topic arch.fonts
.title Font System
.toc 0 Font System
.index Fonts
.index Bitmap Font
.index BitmapFontT
.index Text Rendering
.index CP437
.h1 Font System
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).
.h2 BitmapFontT
.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;
.endcode
Design rationale:
.list
.item Character positions are pure multiplication (x = col * 8).
.item Glyph lookup is a single array index.
.item Each scanline of a glyph is exactly one byte (1bpp at 8 pixels wide).
.item No glyph-width tables, kerning, or per-character positioning needed.
.item 8-pixel width aligns with byte boundaries -- no bit shifting in per-scanline rendering.
.endlist
.h2 Text Rendering Functions
drawChar() -- Renders a single character. Supports opaque (background fill) and transparent modes.
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.
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.
drawTextAccel() -- Renders text with & accelerator markers. The character after & is underlined to indicate the keyboard shortcut.
.h2 Performance Optimization
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.
.topic arch.colors
.title Color System
.toc 0 Color System
.index Colors
.index Pixel Format
.index PixelFormatT
.index ColorSchemeT
.index Theming
.index Bevel
.h1 Color System
.h2 Pixel Format
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.
Supported depths:
.table
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).
.endtable
.h2 ColorSchemeT -- Theming
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.
Color roles mirror classic Motif/Windows 3.x conventions:
.list
.item desktop -- desktop background
.item windowFace, windowHighlight, windowShadow -- window chrome bevel triplet
.item activeTitleBg/Fg, inactiveTitleBg/Fg -- focused vs. unfocused title bar
.item contentBg/Fg -- window content area
.item menuBg/Fg, menuHighlightBg/Fg -- menus
.item buttonFace -- button background
.item scrollbarBg/Fg/Trough -- scrollbar components
.item cursorFg/Bg -- mouse cursor colors
.endlist
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().
.h2 Bevel Styles
Bevels are the defining visual element of the Motif aesthetic. Convenience macros create bevel style descriptors by swapping highlight and shadow colors:
.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
.endcode
.topic arch.platform
.title Platform Layer
.toc 0 Platform Layer
.index Platform Layer
.index dvxPlatform
.index VESA
.index VBE
.index INT 33h
.index INT 16h
.index Assembly
.index rep stosl
.index rep movsd
.h1 Platform Layer
All OS-specific and CPU-specific code is isolated behind dvxPlatform.h. To port DVX, implement a new dvxPlatformXxx.c against this header.
.h2 Implementations
.table
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.
.endtable
.h2 Abstraction Areas
.h3 Video
platformVideoInit() -- mode probe and framebuffer setup. platformVideoShutdown() -- restore previous mode. platformVideoEnumModes() -- enumerate available modes.
.h3 Framebuffer Flush
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.
.h3 Optimized Memory Spans
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.
.h3 Mouse Input
Polling model. platformMousePoll() returns position and button bitmask. Wheel support via CuteMouse API.
.h3 Keyboard Input
platformKeyboardRead() -- non-blocking key read. platformKeyUpRead() -- key release detection (requires INT 9 hook on DOS). platformAltScanToChar() -- scancode-to-ASCII lookup for Alt+key combinations.
.h3 Crash Recovery
platformInstallCrashHandler() -- signal handlers + longjmp for fault tolerance.
.h3 DXE Support
platformRegisterDxeExports() -- register C runtime and platform symbols for DXE resolution. platformRegisterSymOverrides() -- register function pointer overrides for module loader.
.topic arch.build
.title Build System
.toc 0 Build System
.index Build
.index Makefile
.index Cross-Compilation
.index dxe3gen
.index mkcd.sh
.index ISO
.h1 Build System
.h2 Cross-Compilation
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.
.code
make -- build everything
./mkcd.sh -- build + create ISO for 86Box
.endcode
.h2 Build Targets
.code
all: core tasks loader texthelp listhelp tools widgets shell taskmgr serial sql apps
.endcode
.table
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
.endtable
.h2 DXE3 Build Process
Each DXE module is compiled to an object file with GCC, then linked with dxe3gen:
.code
# Compile
i586-pc-msdosdjgpp-gcc -O2 -march=i486 -mtune=i586 -c -o widget.o widget.c
# Link as DXE with exported symbols
dxe3gen -o widget.wgt -E _wgtRegister -U widget.o
# Optionally append resources
dvxres build widget.wgt widget.res
.endcode
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).
.h2 Deployment (mkcd.sh)
.list
.item Runs make all.
.item Verifies critical outputs exist (dvx.exe, libtasks.lib, libdvx.lib, dvxshell.lib).
.item Counts widget modules.
.item 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).
.item Places the ISO at ~/.var/app/net._86box._86Box/data/86Box/dvx.iso for 86Box to mount as CD-ROM.
.endlist
.h2 Compiler Flags
.code
-O2 Optimization level 2
-march=i486 486 instruction set baseline
-mtune=i586 Optimize scheduling for Pentium
-Wall -Wextra Full warnings
.endcode
.h2 Directory Layout
.code
dvxgui/
+-- core/ Core library sources (dvxVideo, dvxDraw, dvxComp, dvxWm, dvxApp, widget infra)
| +-- platform/ Platform abstraction (dvxPlatform.h, dvxPlatformDos.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 (86Box <-> secLink <-> telnet)
+-- sql/ SQLite integration
+-- bin/ Build output (dvx.exe, libs/, widgets/, apps/, config/)
+-- obj/ Intermediate object files
+-- docs/ Documentation
.endcode

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,944 @@
.topic ide.overview
.title DVX BASIC IDE Guide
.toc 0 Overview
.default
.index DVX BASIC
.index IDE
.index Visual Basic
.index Development Environment
.h1 DVX BASIC IDE Guide
DVX BASIC is a Visual BASIC development environment for the DVX GUI System. It provides a VB3-style integrated development environment with a code editor, form designer, project system, and a full interactive debugger -- all running natively on DOS under the DVX windowing system.
This guide covers every feature of the IDE: menus, toolbar, editor, form designer, project management, debugger, and auxiliary windows.
.h2 IDE Windows
The DVX BASIC IDE is modeled after Visual Basic 3.0. It consists of several floating windows arranged on the DVX desktop:
.list
.item Main Toolbar Window -- anchored at the top of the screen. Contains the menu bar, toolbar buttons, and status bar.
.item Code Editor -- the primary editing surface for BASIC source code, with Object/Event dropdowns, syntax highlighting, and line numbers.
.item Form Designer -- a visual design surface for .frm files, showing a WYSIWYG preview of the form with grab handles for resizing controls.
.item Project Explorer -- a tree view listing all files in the project.
.item Toolbox -- a palette of available controls for placing on forms.
.item Properties Panel -- a tree of controls and a list of editable properties for the selected control.
.item Output Window -- displays PRINT output and runtime errors.
.item Immediate Window -- an interactive REPL for evaluating expressions and modifying variables at runtime.
.item Debug Windows -- Locals, Call Stack, Watch, and Breakpoints windows that appear automatically when debugging.
.endlist
The IDE compiles BASIC source into bytecode and runs it in an integrated virtual machine (VM). Programs execute in cooperative slices (10,000 VM steps per slice), yielding to the DVX event loop between slices so the GUI remains responsive.
.link ide.menu.file File Menu
.link ide.menu.edit Edit Menu
.link ide.menu.run Run Menu
.link ide.menu.view View Menu
.link ide.menu.window Window Menu
.link ide.menu.tools Tools Menu
.link ide.menu.help Help Menu
.link ide.toolbar Toolbar
.link ide.editor Code Editor
.link ide.designer Form Designer
.link ide.project Project System
.link ide.properties Properties Panel
.link ide.toolbox Toolbox
.link ide.debugger Debugger
.link ide.debug.locals Locals Window
.link ide.debug.callstack Call Stack Window
.link ide.debug.watch Watch Window
.link ide.debug.breakpoints Breakpoints Window
.link ide.immediate Immediate Window
.link ide.output Output Window
.link ide.findreplace Find / Replace
.link ide.preferences Preferences
.link ide.shortcuts Keyboard Shortcuts
.topic ide.menu.file
.title File Menu
.toc 0 Menu Reference
.toc 1 File Menu
.index File Menu
.index New Project
.index Open Project
.index Save Project
.index Close Project
.index Project Properties
.index Add File
.index Save File
.index Save All
.index Remove File
.index Exit
.h1 File Menu
.table
Menu Item Shortcut Description
--------- -------- -----------
New Project... Create a new DVX BASIC project.
Open Project... Open an existing .dbp project file.
Save Project Save the current project file to disk.
Close Project Close the current project (prompts to save unsaved changes).
---
Project Properties... Edit project metadata (name, author, version, startup form, icon, etc.).
---
Add File... Ctrl+O Add a .bas or .frm file to the project. If no project is open, creates an implicit project from the file.
Save File Ctrl+S Save the active file to disk.
Save All Save all modified files in the project.
---
Remove File Remove the selected file from the project (prompts to save if modified).
---
Exit Close the IDE (prompts to save unsaved changes).
.endtable
.link ide.menu.edit Edit Menu
.link ide.overview Back to Overview
.topic ide.menu.edit
.title Edit Menu
.toc 1 Edit Menu
.index Edit Menu
.index Cut
.index Copy
.index Paste
.index Select All
.index Delete
.index Find
.index Find Next
.index Replace
.h1 Edit Menu
.table
Menu Item Shortcut Description
--------- -------- -----------
Cut Ctrl+X Cut selected text to the clipboard.
Copy Ctrl+C Copy selected text to the clipboard.
Paste Ctrl+V Paste text from the clipboard.
---
Select All Ctrl+A Select all text in the active editor.
---
Delete Del Delete the selected text or control (in the form designer).
---
Find... Ctrl+F Open the Find/Replace dialog.
Find Next F3 Find the next occurrence of the search text.
Replace... Ctrl+H Open the Find/Replace dialog with replace enabled.
.endtable
.link ide.menu.run Run Menu
.link ide.overview Back to Overview
.topic ide.menu.run
.title Run Menu
.toc 1 Run Menu
.index Run Menu
.index Run
.index Debug
.index Run Without Recompile
.index Stop
.index Step Into
.index Step Over
.index Step Out
.index Run to Cursor
.index Toggle Breakpoint
.index Clear Output
.index Save on Run
.h1 Run Menu
.table
Menu Item Shortcut Description
--------- -------- -----------
Run F5 Compile and run the program. If paused at a breakpoint, resumes execution with debugging disabled (runs free).
Debug Shift+F5 Compile and run with the debugger active. Breakpoints are active but execution does not pause at the first statement. If paused, resumes to the next breakpoint.
Run Without Recompile Ctrl+F5 Re-run the last compiled module without recompiling.
Stop Esc Stop the running program immediately.
---
Step Into F8 Execute one statement, stepping into SUB/FUNCTION calls. If idle, starts a debug session and breaks at the first statement.
Step Over Shift+F8 Execute one statement, stepping over SUB/FUNCTION calls.
Step Out Ctrl+Shift+F8 Run until the current SUB/FUNCTION returns.
Run to Cursor Ctrl+F8 Run until execution reaches the line where the cursor is positioned.
---
Toggle Breakpoint F9 Toggle a breakpoint on the current editor line.
---
Clear Output Clear the Output window.
---
Save on Run Checkbox: when enabled, all modified files are saved automatically before compiling. Persisted in preferences.
.endtable
.link ide.menu.view View Menu
.link ide.overview Back to Overview
.topic ide.menu.view
.title View Menu
.toc 1 View Menu
.index View Menu
.index Code View
.index Design View
.index Toolbar Toggle
.index Status Bar Toggle
.index Menu Editor
.h1 View Menu
.table
Menu Item Shortcut Description
--------- -------- -----------
Code F7 Switch to Code view for the active file (or the file selected in the Project Explorer).
Designer Shift+F7 Switch to Design view for the active form file.
---
Toolbar Checkbox: show or hide the toolbar. Persisted in preferences.
Status Bar Checkbox: show or hide the status bar. Persisted in preferences.
---
Menu Editor... Ctrl+E Open the Menu Editor dialog for the active form. Allows designing menu bars with captions, names, levels, checked state, and enabled state.
.endtable
.link ide.menu.window Window Menu
.link ide.overview Back to Overview
.topic ide.menu.window
.title Window Menu
.toc 1 Window Menu
.index Window Menu
.h1 Window Menu
.table
Menu Item Description
--------- -----------
Code Editor Show or raise the Code Editor window.
Output Show or raise the Output window.
Immediate Show or raise the Immediate window.
Locals Show or raise the Locals debug window.
Call Stack Show or raise the Call Stack debug window.
Watch Show or raise the Watch debug window.
Breakpoints Show or raise the Breakpoints window.
---
Project Explorer Show or raise the Project Explorer window.
Toolbox Show or raise the Toolbox window.
Properties Show or raise the Properties panel.
.endtable
.link ide.menu.tools Tools Menu
.link ide.overview Back to Overview
.topic ide.menu.tools
.title Tools Menu
.toc 1 Tools Menu
.index Tools Menu
.index Preferences
.index Debug Layout
.h1 Tools Menu
.table
Menu Item Description
--------- -----------
Preferences... Open the Preferences dialog (editor settings and project defaults).
---
Debug Layout Checkbox: toggle a debug overlay that shows widget layout boundaries. Useful for diagnosing widget layout issues.
.endtable
.link ide.menu.help Help Menu
.link ide.overview Back to Overview
.topic ide.menu.help
.title Help Menu
.toc 1 Help Menu
.index Help Menu
.index About
.h1 Help Menu
.table
Menu Item Description
--------- -----------
About DVX BASIC... Show the About dialog with version and copyright information.
.endtable
.link ide.overview Back to Overview
.topic ide.toolbar
.title Toolbar
.toc 0 Toolbar
.index Toolbar
.h1 Toolbar
The toolbar is organized into four groups separated by vertical dividers. Each button has a tooltip showing its name and keyboard shortcut.
.h2 File Group
.table
Button Shortcut Action
------ -------- ------
Open Ctrl+O Add a file to the project (same as File > Add File).
Save Ctrl+S Save the active file.
.endtable
.h2 Run Group
.table
Button Shortcut Action
------ -------- ------
Run F5 Compile and run the program.
Stop Esc Stop the running program.
.endtable
.h2 Debug Group
.table
Button Shortcut Action
------ -------- ------
Debug Shift+F5 Start or resume a debug session.
Step Into F8 Step into the next statement.
Step Over Shift+F8 Step over the next statement.
Step Out Ctrl+Shift+F8 Step out of the current procedure.
Run to Cursor Ctrl+F8 Run to the cursor position.
.endtable
.h2 View Group
.table
Button Shortcut Action
------ -------- ------
Code F7 Switch to Code view.
Design Shift+F7 Switch to Design view.
.endtable
.link ide.overview Back to Overview
.topic ide.editor
.title Code Editor
.toc 0 Code Editor
.index Code Editor
.index Syntax Highlighting
.index Object Dropdown
.index Function Dropdown
.index Line Numbers
.index Auto-indent
.h1 Code Editor
The Code Editor is the primary editing window for BASIC source code. It occupies the center of the screen, below the toolbar and above the Output and Immediate windows.
.h2 Object and Function Dropdowns
At the top of the Code Editor are two dropdown lists:
.list
.item Object -- lists (General) plus all objects (form name, control names, menu item names). Selecting an object filters the Function dropdown.
.item Function -- lists all event handlers (procedures) for the selected object. Implemented handlers are listed first (plain text); unimplemented handlers follow in brackets (e.g., [Click]). Selecting an unimplemented event creates a new event handler stub.
.endlist
The editor shows one procedure at a time. Each procedure has its own buffer, and switching between them is instantaneous. The (General) section contains module-level declarations and code.
.h2 Syntax Highlighting
The editor applies real-time syntax coloring as you type. The following categories are highlighted in distinct colors:
.table
Category Examples
-------- --------
Keywords IF, THEN, FOR, NEXT, SUB, FUNCTION, DIM, PRINT, SELECT, CASE, DO, LOOP, WHILE, WEND, END, EXIT, CALL, GOSUB, GOTO, RETURN, DECLARE, CONST, TYPE, AND, OR, NOT, XOR, MOD, etc.
Type names INTEGER, LONG, SINGLE, DOUBLE, STRING, BOOLEAN, BYTE, TRUE, FALSE
String literals "Hello, World!"
Comments ' This is a comment, REM This is a comment
Numbers 42, 3.14
Operators =, <, >, +, -, *, /, \, &
.endtable
.h2 Editor Features
.list
.item Line numbers -- displayed in the gutter on the left side.
.item Auto-indent -- new lines are automatically indented to match the previous line.
.item Tab handling -- the Tab key is captured by the editor. Tab width and whether to insert spaces or tab characters are configurable in Preferences (default: 3 spaces).
.item Gutter click -- clicking in the line number gutter toggles a breakpoint on that line.
.item Line decorations -- breakpoint lines show a red dot in the gutter. The current debug line (when paused) is highlighted with a yellow background.
.endlist
.link ide.overview Back to Overview
.topic ide.designer
.title Form Designer
.toc 0 Form Designer
.index Form Designer
.index Design Surface
.index Grid Snapping
.index Grab Handles
.index Control Placement
.index WYSIWYG
.h1 Form Designer
The Form Designer provides a visual design surface for editing .frm files. Switch to it with Shift+F7 or the Design toolbar button. It opens in a separate window showing a WYSIWYG preview of the form.
.h2 Design Surface
.list
.item Grid snapping -- controls snap to an 8-pixel grid (DSGN_GRID_SIZE) when placed or resized.
.item Selection -- click a control to select it. The selected control is highlighted with grab handles.
.item Grab handles -- 6x6 pixel handles appear on the right edge (E), bottom edge (S), and bottom-right corner (SE) of the selected control. Drag a handle to resize the control.
.item Reordering -- drag a control vertically to reorder it within the form's layout (VBox/HBox).
.item Placing controls -- select a control type in the Toolbox, then click on the form to place a new instance. The control is auto-named (e.g., Command1, Command2). Clicking the same tool again deselects it (toggles back to pointer mode).
.item Menu bar preview -- if the form has menu items (defined via the Menu Editor), a preview menu bar is rendered on the design window.
.item Delete key -- removes the selected control from the form.
.endlist
.h2 Form Properties
Forms have the following design-time properties: Name, Caption, Width, Height, Left, Top, Layout (VBox or HBox), Centered, AutoSize, and Resizable.
.link ide.properties Properties Panel
.link ide.toolbox Toolbox
.link ide.overview Back to Overview
.topic ide.project
.title Project System
.toc 0 Project System
.index Project System
.index Project Files
.index .dbp Files
.index Project Explorer
.index Source Map
.h1 Project System
.h2 Project Files (.dbp)
A DVX BASIC project is stored as a .dbp file (DVX BASIC Project). The project file records:
.list
.item Name -- the project display name (up to 32 characters).
.item Startup Form -- which form to show automatically when the program starts.
.item Metadata -- Author, Company, Version, Copyright, Description, and Icon Path (for compiled binaries).
.item File list -- relative paths (8.3 DOS names) of all .bas and .frm files in the project. Each entry tracks whether it is a form file.
.endlist
.h2 Source Map
When the project is compiled, all files are concatenated into a single source stream. A source map tracks which lines belong to which file, enabling accurate error reporting and debugger navigation across multiple files. For .frm files, an injected BEGINFORM directive is prepended to the code section.
.h2 Project Operations
.table
Operation Description
--------- -----------
New Project Creates a blank project with a name and directory. A default .frm file is added automatically.
Open Project Opens a .dbp file and loads all referenced files into memory.
Save Project Writes the .dbp file to disk.
Close Project Closes the project, prompting to save unsaved changes.
Add File Adds a .bas or .frm file to the project. Opening a file without a project auto-creates an implicit project.
Remove File Removes a file from the project (prompts to save if modified).
Project Properties Opens a dialog for editing project metadata (name, author, company, version, copyright, description, icon, startup form).
.endtable
.h2 Project Explorer
The Project Explorer is a tree view window listing all project files. Double-click a file to open it: .bas files open in Code view, .frm files open in Design view. The selected file in the Project Explorer determines the target for View > Code and View > Designer commands.
.link ide.overview Back to Overview
.topic ide.properties
.title Properties Panel
.toc 0 Properties Panel
.index Properties Panel
.index Control Properties
.index Property List
.index Control Tree
.h1 Properties Panel
The Properties panel (Window > Properties) has two sections:
.list
.item Control tree -- a TreeView at the top listing the form and all its controls in layout order. Click a control name to select it in both the Properties panel and the Form Designer. Drag items in the tree to reorder controls in the form's layout.
.item Property list -- a two-column ListView below the tree showing property names and values for the selected control. Double-click a property value to edit it via an InputBox dialog. Changes take effect immediately in the designer preview.
.endlist
Each control type exposes different properties (e.g., Caption, Text, Width, Height, MaxWidth, MaxHeight, Weight, Alignment, Enabled, Visible, and type-specific properties like DataSource and DataField for data-bound controls).
.link ide.designer Form Designer
.link ide.overview Back to Overview
.topic ide.toolbox
.title Toolbox
.toc 0 Toolbox
.index Toolbox
.index Controls
.index Widget Palette
.h1 Toolbox
The Toolbox (Window > Toolbox) is a floating palette of buttons, one for each available control type. Controls are loaded dynamically from the widget plugin registry -- any widget DXE that provides a basName appears in the toolbox.
Click a tool to select it (the active tool name is stored in the designer state), then click on the form to place a new instance. Click the same tool again to deselect it and return to pointer mode.
.h2 Available Controls
.table
VB Name Description
------- -----------
CommandButton Push button that triggers a Click event.
Label Static text label.
TextBox Single-line text input field.
TextArea Multi-line text editor.
CheckBox On/off checkbox.
OptionButton Radio button (mutually exclusive within a group).
ListBox Scrollable list of items.
ComboBox Drop-down combo box.
DropDown Simple drop-down list.
PictureBox Canvas for drawing and images.
Image Static image display.
ImageButton Clickable image button.
Frame Grouping container with a labeled border.
VBox Vertical layout container.
HBox Horizontal layout container.
WrapBox Flow layout container that wraps items to the next row.
Splitter Resizable split between two child panes.
ScrollPane Scrollable container for large content.
TabStrip Tabbed container with multiple pages.
ListView Multi-column list with headers.
TreeView Hierarchical tree control.
ProgressBar Progress indicator bar.
HScrollBar Horizontal slider/scrollbar.
SpinButton Numeric up/down spinner.
Line Horizontal or vertical separator line.
Spacer Invisible spacing element for layout.
Timer Non-visual timer that fires periodic events.
Toolbar Toolbar container for buttons.
StatusBar Status bar at the bottom of a form.
Terminal ANSI terminal emulator control.
Data Data control for binding to a database.
DBGrid Data-bound grid for displaying database query results.
.endtable
.link ide.designer Form Designer
.link ide.overview Back to Overview
.topic ide.debugger
.title Debugger
.toc 0 Debugger
.index Debugger
.index Breakpoints
.index Stepping
.index Debug Mode
.index DBG_IDLE
.index DBG_RUNNING
.index DBG_PAUSED
.h1 Debugger
The DVX BASIC IDE includes a full interactive debugger. The debugger operates as a state machine with three states:
.table
State Description
----- -----------
DBG_IDLE No program loaded or running.
DBG_RUNNING Program is executing (VM running in slices).
DBG_PAUSED Execution is paused at a breakpoint or step point. The IDE GUI is fully interactive.
.endtable
.h2 Starting a Debug Session
.list
.item Shift+F5 (Debug) -- compiles the project and starts execution in debug mode. Breakpoints are active but execution does not pause at the first statement.
.item F8 (Step Into) -- if idle, starts a debug session and breaks at the first statement.
.item F5 (Run) -- compiles and runs without the debugger. No breakpoints are active. If already paused, resumes execution with debugging disabled.
.endlist
.h2 Breakpoints
.h3 Setting Breakpoints
.list
.item Press F9 to toggle a breakpoint on the current editor line.
.item Click in the line number gutter to toggle a breakpoint on that line.
.endlist
.h3 Breakpoint Validation
Not every line can have a breakpoint. The IDE validates the line content and silently refuses to set breakpoints on:
.list
.item Blank lines
.item Comment lines (' or REM)
.item SUB and FUNCTION declaration lines
.item END SUB and END FUNCTION lines
.endlist
.h3 Breakpoint Storage
Each breakpoint records the project file index, the code line number within the file, the procedure index, and the procedure name (as Object.Event). When the project is compiled, breakpoints are converted to concatenated source line numbers that match the VM's OP_LINE opcodes.
.h3 Visual Indicators
.list
.item Breakpoint lines show a red dot in the gutter.
.item The current debug line (when paused) has a yellow background.
.endlist
.h3 Breakpoint Adjustment on Edit
When lines are added or removed in the editor, breakpoints below the edit point are automatically shifted to stay on the correct line.
.h2 Stepping
.table
Action Shortcut Behavior
------ -------- --------
Step Into F8 Execute one statement. If the statement is a SUB/FUNCTION call, step into it.
Step Over Shift+F8 Execute one statement. If the statement is a SUB/FUNCTION call, execute the entire call and break at the next line in the current scope.
Step Out Ctrl+Shift+F8 Run until the current SUB/FUNCTION returns to its caller.
Run to Cursor Ctrl+F8 Run until execution reaches the line under the cursor.
.endtable
.h2 The Debug Run Loop
When a program is running in debug mode, the IDE enters a cooperative loop:
.list
.item The VM executes up to 10,000 steps per slice.
.item If the VM hits a breakpoint (BAS_VM_BREAKPOINT), the state transitions to DBG_PAUSED. The IDE navigates the code editor to the breakpoint line, highlights it in yellow, auto-opens the Locals and Call Stack windows, and updates all debug windows.
.item While paused, the IDE pumps dvxUpdate() continuously, keeping the GUI responsive. The user can inspect variables, modify them in the Immediate window, step, continue, or stop.
.item When the user resumes (F5/Shift+F5/F8/etc.), the state transitions back to DBG_RUNNING and the loop continues.
.endlist
.h2 Stopping
Press Esc or click the Stop toolbar button at any time to halt execution. The VM is destroyed, debug state resets to DBG_IDLE, and the IDE restores the designer windows that were hidden at run start.
.link ide.debug.locals Locals Window
.link ide.debug.callstack Call Stack Window
.link ide.debug.watch Watch Window
.link ide.debug.breakpoints Breakpoints Window
.link ide.overview Back to Overview
.topic ide.debug.locals
.title Locals Window
.toc 0 Debug Windows
.toc 1 Locals Window
.index Locals Window
.index Variable Inspection
.h1 Locals Window
When the debugger pauses, the Locals and Call Stack windows are auto-opened (if not already visible). The Watch and Breakpoints windows can be opened manually from the Window menu.
Shows variables for the current execution scope. Displayed as a three-column ListView:
.table
Column Content
------ -------
Name Variable name (internal mangled names like static variable placeholders are filtered out).
Type Data type: Integer, Long, Single, Double, String, Boolean, Array, UDT. Array types show the element type (e.g., Integer()).
Value Current value. Strings are shown in quotes. Booleans as True/False. Arrays show bounds and element count (e.g., Integer(0 To 9) [10]). Uninitialized arrays show (uninitialized).
.endtable
The Locals window displays:
.list
.item Local variables for the current procedure (matched by proc index).
.item Global (module-level) variables.
.item Form-scoped variables for the current form (if the program is executing within a form context).
.endlist
Up to 64 variables are displayed. The window is resizable.
.link ide.debug.callstack Call Stack Window
.link ide.overview Back to Overview
.topic ide.debug.callstack
.title Call Stack Window
.toc 1 Call Stack Window
.index Call Stack
.index Stack Trace
.h1 Call Stack Window
Shows the current call chain as a two-column ListView:
.table
Column Content
------ -------
Procedure Procedure name (or (module) for module-level code).
Line Line number where execution is paused (shown for the topmost frame).
.endtable
The current location is shown first, followed by each caller in the call stack (walking from the deepest frame back to the module entry point). Up to 32 frames are displayed.
.link ide.debug.watch Watch Window
.link ide.overview Back to Overview
.topic ide.debug.watch
.title Watch Window
.toc 1 Watch Window
.index Watch Window
.index Watch Expressions
.h1 Watch Window
Allows monitoring arbitrary expressions while debugging. The window has a text input at the top and a two-column ListView below:
.table
Column Content
------ -------
Expression The watch expression text.
Value Evaluated result (or <error> if evaluation fails). Blank when not paused.
.endtable
.h2 Adding Watch Expressions
Type an expression in the text input and press Enter. Up to 16 watch expressions can be active at once.
.h2 Watch Expression Syntax
Watch expressions support:
.list
.item Simple variable names: x, count
.item Array subscripts: arr(5), matrix(2, 3)
.item UDT field access: player.name
.item Combined: items(i).price
.item Arbitrary BASIC expressions (compiled and evaluated against the paused VM's state): x + y * 2, Len(name$)
.endlist
.h2 Editing and Deleting
.list
.item Double-click or press Enter on a watch entry to move it back into the input box for editing.
.item Press Delete to remove the selected watch expression.
.endlist
.link ide.debug.breakpoints Breakpoints Window
.link ide.overview Back to Overview
.topic ide.debug.breakpoints
.title Breakpoints Window
.toc 1 Breakpoints Window
.index Breakpoints Window
.h1 Breakpoints Window
Lists all set breakpoints as a three-column ListView:
.table
Column Content
------ -------
File Project file path.
Procedure Procedure name (Object.Event format, or (General)).
Line Code line number within the file.
.endtable
.list
.item Double-click a breakpoint to navigate the code editor to that location.
.item Press Delete to remove selected breakpoints (multi-select is supported).
.endlist
.link ide.debugger Debugger
.link ide.overview Back to Overview
.topic ide.immediate
.title Immediate Window
.toc 0 Immediate Window
.index Immediate Window
.index REPL
.index Expression Evaluation
.index Variable Assignment
.h1 Immediate Window
The Immediate window is an interactive REPL at the bottom-right of the screen. Type a line of BASIC and press Enter to evaluate it. Results appear inline below your input.
.h2 Expression Evaluation
If the input is not a recognized statement keyword, it is automatically wrapped in a PRINT statement. For example, typing 2 + 2 evaluates as PRINT 2 + 2 and displays 4.
You can also type full statements:
.list
.item PRINT x * 2 -- evaluate and print an expression.
.item DIM tmp As Integer -- declare a temporary variable.
.item LET x = 42 -- explicit assignment (see below).
.endlist
Parse or runtime errors are displayed inline with an Error: prefix.
.h2 Inspecting Variables While Paused
When the debugger is paused at a breakpoint, the Immediate window has access to the running VM's state. Global variable values are copied into the evaluation VM, so expressions like count or name$ & " test" display live values.
.h2 Assigning Variables While Paused
When paused, you can modify variables in the running program directly from the Immediate window using assignment syntax:
.code
variableName = newValue
.endcode
The optional LET keyword is also accepted:
.code
LET variableName = newValue
.endcode
Assignment works for:
.list
.item Scalar variables -- x = 42, name$ = "test"
.item Array elements -- arr(5) = 100, matrix(2, 3) = 7.5
.item UDT fields -- player.score = 1000
.item Combined -- items(0).price = 9.99
.endlist
The new value is written directly into the VM's live variable slot (local, global, or form scope). A confirmation message is displayed, and the Locals and Watch windows update automatically to reflect the change.
If the assignment target cannot be resolved (unknown variable, out-of-bounds index, wrong type), an error message is displayed.
.link ide.overview Back to Overview
.topic ide.output
.title Output Window
.toc 0 Output Window
.index Output Window
.index PRINT Output
.index Runtime Errors
.index Compile Errors
.h1 Output Window
The Output window is a read-only TextArea at the bottom-left of the screen. It displays:
.list
.item PRINT output -- all PRINT statement output from the running program is appended here.
.item Runtime errors -- if the VM encounters a runtime error (division by zero, out-of-bounds, etc.), the error message and line number are displayed in the output with an Error on line N: prefix.
.item Compile errors -- if compilation fails, the error message and location are shown.
.endlist
The output buffer holds up to 32,768 characters. Use Run > Clear Output to clear it.
INPUT statements prompt the user via a modal InputBox dialog; the prompt text is also echoed to the Output window.
.link ide.overview Back to Overview
.topic ide.findreplace
.title Find / Replace
.toc 0 Find / Replace
.index Find
.index Replace
.index Find Next
.index Search
.h1 Find / Replace
Open with Ctrl+F (Find) or Ctrl+H (Replace). The Find/Replace dialog is modeless -- it stays open while you continue editing.
.h2 Dialog Controls
.table
Control Description
------- -----------
Find input The text to search for.
Replace checkbox + input Enable replacement mode and enter replacement text.
Scope Radio group: Function, Object, File, or Project. Default is Project.
Direction Radio group: Forward or Backward.
Match Case Checkbox: case-sensitive search.
.endtable
.h2 Buttons
.table
Button Action
------ ------
Find Next Find the next occurrence. Wraps across procedures, files, and the entire project depending on the scope setting.
Replace Replace the current match and find the next one.
Replace All Replace all occurrences within the selected scope.
Close Close the dialog.
.endtable
.h2 Keyboard Shortcut
F3 repeats the last search (Find Next) without opening the dialog.
.link ide.overview Back to Overview
.topic ide.preferences
.title Preferences
.toc 0 Preferences
.index Preferences
.index Settings
.index Tab Width
.index Option Explicit
.h1 Preferences
Open via Tools > Preferences. Settings are saved to dvxbasic.ini in the app's config directory.
.h2 Editor Section
.table
Setting Description Default
------- ----------- -------
Skip comments/strings when renaming When renaming a control or form, skip occurrences inside comments and string literals. On
Require variable declaration (OPTION EXPLICIT) When enabled, variables must be declared with DIM before use. Off
Tab width Number of spaces per tab stop (1-8). 3
Insert spaces instead of tabs When enabled, pressing Tab inserts spaces. When disabled, inserts a real tab character. On
.endtable
.h2 New Project Defaults Section
These fields set the default values for new project metadata:
.table
Field Description Default
----- ----------- -------
Author Default author name. (empty)
Company Default company name. (empty)
Version Default version string. 1.0
Copyright Default copyright notice. (empty)
Description Default project description (multi-line). (empty)
.endtable
.link ide.overview Back to Overview
.topic ide.shortcuts
.title Keyboard Shortcuts
.toc 0 Keyboard Shortcuts
.index Keyboard Shortcuts
.index Hotkeys
.index Accelerators
.h1 Keyboard Shortcuts
.table
Shortcut Action
-------- ------
Ctrl+O Add File
Ctrl+S Save File
Ctrl+A Select All
Ctrl+X Cut
Ctrl+C Copy
Ctrl+V Paste
Ctrl+F Find
Ctrl+H Replace
Ctrl+E Menu Editor
F3 Find Next
F5 Run
Shift+F5 Debug
Ctrl+F5 Run Without Recompile
Esc Stop
F7 Code View
Shift+F7 Design View
F8 Step Into
Shift+F8 Step Over
Ctrl+Shift+F8 Step Out
Ctrl+F8 Run to Cursor
F9 Toggle Breakpoint
Del Delete
.endtable
.hr
DVX BASIC 1.0 -- Copyright 2026 Scott Duensing

File diff suppressed because it is too large Load diff

View file

@ -6,7 +6,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I. -I../core -I../core/platform -I../tasks -I../core/thirdparty
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I. -I../core -I../core/platform -I../tasks -I../core/thirdparty
OBJDIR = ../obj/listhelp
LIBSDIR = ../bin/libs

View file

@ -9,7 +9,7 @@ DJGPP_LIBPATH = $(HOME)/claude/windriver/tools/lib
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
EXE2COFF = $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/exe2coff
CWSDSTUB = $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/CWSDSTUB.EXE
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I../core -I../core/platform -I../tasks -I../core/thirdparty
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I../core -I../core/platform -I../tasks -I../core/thirdparty
LDFLAGS = -lm
OBJDIR = ../obj/loader

View file

@ -243,7 +243,7 @@ static void scanDir(const char *dirPath, const char *ext, ModuleT **mods) {
}
char path[DVX_MAX_PATH];
snprintf(path, sizeof(path), "%s/%s", dirPath, name);
snprintf(path, sizeof(path), "%s%c%s", dirPath, DVX_PATH_SEP, name);
// Check for matching extension
int32_t nameLen = strlen(name);

View file

@ -5,7 +5,7 @@ DJGPP_LIBPATH = $(HOME)/claude/windriver/tools/lib
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
AR = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ar
RANLIB = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ranlib
CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-format-truncation -march=i486 -mtune=i586
OBJDIR = ../obj/packet
LIBDIR = ../lib

View file

@ -3,7 +3,7 @@
# shim instead of the DJGPP rs232 driver.
CC = gcc
CFLAGS = -O2 -Wall -Wextra
CFLAGS = -O2 -Wall -Wextra -Werror
OBJDIR = ../obj/proxy
BINDIR = ../bin

View file

@ -5,7 +5,7 @@ DJGPP_LIBPATH = $(HOME)/claude/windriver/tools/lib
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
AR = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ar
RANLIB = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ranlib
CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-format-truncation -march=i486 -mtune=i586
OBJDIR = ../obj/rs232
LIBDIR = ../lib

View file

@ -5,7 +5,7 @@ DJGPP_LIBPATH = $(HOME)/claude/windriver/tools/lib
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
AR = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ar
RANLIB = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ranlib
CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-format-truncation -march=i486 -mtune=i586
OBJDIR = ../obj/seclink
LIBDIR = ../lib

View file

@ -5,7 +5,7 @@ DJGPP_LIBPATH = $(HOME)/claude/windriver/tools/lib
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
AR = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ar
RANLIB = LD_LIBRARY_PATH=$(DJGPP_LIBPATH) $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-ranlib
CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-format-truncation -march=i486 -mtune=i586
OBJDIR = ../obj/security
LIBDIR = ../lib

View file

@ -6,7 +6,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586 -I../rs232 -I../packet -I../security -I../seclink -I../core -I../core/platform -I../tasks
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-format-truncation -march=i486 -mtune=i586 -I../rs232 -I../packet -I../security -I../seclink -I../core -I../core/platform -I../tasks
OBJDIR = ../obj/serial
LIBSDIR = ../bin/libs

View file

@ -5,7 +5,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I../core -I../core/platform -I../widgets -I../tasks -I../core/thirdparty
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I../core -I../core/platform -I../widgets -I../tasks -I../core/thirdparty
OBJDIR = ../obj/shell
LIBSDIR = ../bin/libs

View file

@ -219,7 +219,7 @@ void shellAppInit(void) {
// ============================================================
void shellConfigPath(const DxeAppContextT *ctx, const char *filename, char *outPath, int32_t outSize) {
snprintf(outPath, outSize, "%s/%s", ctx->configDir, filename);
snprintf(outPath, outSize, "%s%c%s", ctx->configDir, DVX_PATH_SEP, filename);
}
@ -299,7 +299,20 @@ ShellAppT *shellGetApp(int32_t appId) {
// unique temp file before dlopen, giving each instance its own code+data.
// If multiInstance=false (the default), a second load of the same path is
// blocked with an error message.
static int32_t shellLoadAppInternal(AppContextT *ctx, const char *path, const char *args);
int32_t shellLoadApp(AppContextT *ctx, const char *path) {
return shellLoadAppInternal(ctx, path, NULL);
}
int32_t shellLoadAppWithArgs(AppContextT *ctx, const char *path, const char *args) {
return shellLoadAppInternal(ctx, path, args);
}
static int32_t shellLoadAppInternal(AppContextT *ctx, const char *path, const char *args) {
// Allocate a slot
int32_t id = allocSlot();
@ -457,6 +470,11 @@ int32_t shellLoadApp(AppContextT *ctx, const char *path) {
snprintf(app->dxeCtx->configDir, sizeof(app->dxeCtx->configDir), "CONFIG/APPS/%s", desc->name);
}
// Copy launch arguments (if any)
if (args && args[0]) {
snprintf(app->dxeCtx->args, sizeof(app->dxeCtx->args), "%s", args);
}
// Launch. Set currentAppId before any app code runs so that
// dvxCreateWindow stamps the correct owner on new windows.
ctx->currentAppId = id;

View file

@ -65,6 +65,9 @@ typedef struct {
char appPath[DVX_MAX_PATH]; // full path to the .app file
char appDir[DVX_MAX_PATH]; // directory containing the .app file
char configDir[DVX_MAX_PATH]; // writable config directory (CONFIG/<apppath>/)
char args[1024]; // launch arguments (empty if none)
char helpFile[DVX_MAX_PATH]; // help file path (for F1 context help)
char helpTopic[128]; // current help topic ID (updated by app)
} DxeAppContextT;
// ============================================================
@ -115,6 +118,10 @@ void shellAppInit(void);
// app starts running on the next tsYield.
int32_t shellLoadApp(AppContextT *ctx, const char *path);
// Load and run an app with arguments. The args string is copied into
// DxeAppContextT.args before appMain is called.
int32_t shellLoadAppWithArgs(AppContextT *ctx, const char *path, const char *args);
// Reap finished apps (call each frame from main loop). Returns true if
// any apps were reaped, so the caller can notify the desktop to refresh.
// For callback-only apps, termination is triggered by shellWrapDestroyWindow

View file

@ -87,6 +87,47 @@ static void ctrlEscHandler(void *ctx) {
}
// ============================================================
// f1HelpHandler -- system-wide F1 launches context-sensitive help
// ============================================================
#define HELP_VIEWER_PATH "APPS/DVXHELP/DVXHELP.APP"
#define SYSTEM_HELP_FILE "APPS/DVXHELP/DVXHELP.HLP"
static void f1HelpHandler(void *ctx) {
AppContextT *ac = (AppContextT *)ctx;
// Find the focused window's owning app
char args[1024] = {0};
int32_t focusedAppId = 0;
if (ac->stack.focusedIdx >= 0) {
WindowT *win = ac->stack.windows[ac->stack.focusedIdx];
focusedAppId = win->appId;
}
if (focusedAppId > 0) {
ShellAppT *app = shellGetApp(focusedAppId);
if (app && app->dxeCtx && app->dxeCtx->helpFile[0]) {
if (app->dxeCtx->helpTopic[0]) {
snprintf(args, sizeof(args), "%s %s",
app->dxeCtx->helpFile, app->dxeCtx->helpTopic);
} else {
snprintf(args, sizeof(args), "%s", app->dxeCtx->helpFile);
}
}
}
// Fall back to system help if no app-specific help
if (!args[0]) {
snprintf(args, sizeof(args), "%s", SYSTEM_HELP_FILE);
}
shellLoadAppWithArgs(ac, HELP_VIEWER_PATH, args);
}
// ============================================================
// titleChangeHandler -- refresh listeners when a window title changes
// ============================================================
@ -214,6 +255,8 @@ int shellMain(int argc, char *argv[]) {
sCtx.idleCtx = &sCtx;
sCtx.onCtrlEsc = ctrlEscHandler;
sCtx.ctrlEscCtx = &sCtx;
sCtx.onF1 = f1HelpHandler;
sCtx.f1Ctx = &sCtx;
sCtx.onTitleChange = titleChangeHandler;
sCtx.titleChangeCtx = &sCtx;

View file

@ -17,7 +17,7 @@ SQLITE_DIR = thirdparty/sqlite
SQLITE_SRC = $(SQLITE_DIR)/src
SQLITE_TOOL = $(SQLITE_DIR)/tool
CFLAGS = -O2 -Wall -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 \
CFLAGS = -O2 -Wall -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -Wno-address -march=i486 -mtune=i586 \
-I../core -I../core/platform -I../tasks \
-DSQLITE_THREADSAFE=0 -DSQLITE_OMIT_LOAD_EXTENSION \
-I$(SQLITE_SRC) -I$(SQLITE_DIR)/examples -I$(OBJDIR)

View file

@ -1192,6 +1192,7 @@ int sqlite3BtreeOpen(
}
sqlite3OsFullPathname(pVfs, zFilename, nFullPathname, zFullPathname);
mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
(void)mutexShared;
sqlite3_mutex_enter(mutexShared);
for(pBt=sqlite3SharedCacheList; pBt; pBt=pBt->pNext){
assert( pBt->nRef>0 );
@ -1295,6 +1296,7 @@ int sqlite3BtreeOpen(
sqlite3_mutex *mutexShared;
pBt->nRef = 1;
mutexShared = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
(void)mutexShared;
if( SQLITE_THREADSAFE ){
pBt->mutex = sqlite3_mutex_alloc(SQLITE_MUTEX_FAST);
if( pBt->mutex==0 ){
@ -1370,6 +1372,7 @@ static int removeFromSharingList(BtShared *pBt){
assert( sqlite3_mutex_notheld(pBt->mutex) );
pMaster = sqlite3_mutex_alloc(SQLITE_MUTEX_STATIC_MASTER);
(void)pMaster;
sqlite3_mutex_enter(pMaster);
pBt->nRef--;
if( pBt->nRef<=0 ){

View file

@ -367,6 +367,7 @@ static void sqliteDeleteIndex(Index *p){
const char *zName = p->zName;
pOld = sqlite3HashInsert(&p->pSchema->idxHash, zName, strlen( zName)+1, 0);
(void)pOld;
assert( pOld==0 || pOld==p );
freeIndex(p);
}
@ -3128,7 +3129,7 @@ SrcList *sqlite3SrcListAppendFromTerm(
** operator with A. This routine shifts that operator over to B.
*/
void sqlite3SrcListShiftJoinType(SrcList *p){
if( p && p->a ){
if( p ){
int i;
for(i=p->nSrc-1; i>0; i--){
p->a[i].jointype = p->a[i-1].jointype;

View file

@ -370,13 +370,13 @@ void sqlite3Insert(
int appendFlag = 0; /* True if the insert is likely to be an append */
/* Register allocations */
int regFromSelect; /* Base register for data coming from SELECT */
int regFromSelect = 0; /* Base register for data coming from SELECT */
int regAutoinc = 0; /* Register holding the AUTOINCREMENT counter */
int regRowCount = 0; /* Memory cell used for the row counter */
int regIns; /* Block of regs holding rowid+data being inserted */
int regRowid; /* registers holding insert rowid */
int regData; /* register holding first column to insert */
int regRecord; /* Holds the assemblied row record */
int regData = 0; /* register holding first column to insert */
int regRecord = 0; /* Holds the assemblied row record */
int *aRegIdx = 0; /* One register allocated to each index */
@ -673,6 +673,7 @@ void sqlite3Insert(
** the content of the new row, and the assemblied row record.
*/
regRecord = ++pParse->nMem;
(void)regRecord;
regRowid = regIns = pParse->nMem+1;
pParse->nMem += pTab->nCol + 1;
if( IsVirtual(pTab) ){
@ -680,6 +681,7 @@ void sqlite3Insert(
pParse->nMem++;
}
regData = regRowid+1;
(void)regData;
/* Run the BEFORE and INSTEAD OF triggers, if there are any
*/
@ -1028,7 +1030,7 @@ void sqlite3GenerateConstraintChecks(
Vdbe *v;
int nCol;
int onError;
int j1, j2, j3; /* Addresses of jump instructions */
int j1, j2 = 0, j3; /* Addresses of jump instructions */
int regData; /* Register containing first data column */
int iCur;
Index *pIdx;

View file

@ -449,7 +449,7 @@ static int lockTrace(int fd, int op, struct flock *p){
if( s==(-1) && op==F_SETLK && (p->l_type==F_RDLCK || p->l_type==F_WRLCK) ){
struct flock l2;
l2 = *p;
fcntl(fd, F_GETLK, &l2);
(void)fcntl(fd, F_GETLK, &l2);
if( l2.l_type==F_RDLCK ){
zType = "RDLCK";
}else if( l2.l_type==F_WRLCK ){
@ -1083,7 +1083,7 @@ static int unixCheckReservedLock(sqlite3_file *id){
lock.l_start = RESERVED_BYTE;
lock.l_len = 1;
lock.l_type = F_WRLCK;
fcntl(pFile->h, F_GETLK, &lock);
(void)fcntl(pFile->h, F_GETLK, &lock);
if( lock.l_type!=F_UNLCK ){
r = 1;
}
@ -1163,6 +1163,7 @@ static int unixLock(sqlite3_file *id, int locktype){
struct lockInfo *pLock = pFile->pLock;
struct flock lock;
int s;
(void)lock;
assert( pFile );
OSTRACE7("LOCK %d %s was %s(%s,%d) pid=%d\n", pFile->h,
@ -2261,7 +2262,7 @@ static int fillInUnixFile(
int rc;
#ifdef FD_CLOEXEC
fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC);
(void)fcntl(h, F_SETFD, fcntl(h, F_GETFD, 0) | FD_CLOEXEC);
#endif
enterMutex();
@ -2307,7 +2308,7 @@ static int openDirectory(const char *zFilename, int *pFd){
fd = open(zDirname, O_RDONLY|O_BINARY, 0);
if( fd>=0 ){
#ifdef FD_CLOEXEC
fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
(void)fcntl(fd, F_SETFD, fcntl(fd, F_GETFD, 0) | FD_CLOEXEC);
#endif
OSTRACE3("OPENDIR %-3d %s\n", fd, zDirname);
}

View file

@ -246,6 +246,7 @@ static void vxprintf(
char buf[etBUFSIZE]; /* Conversion buffer */
char prefix; /* Prefix character. "+" or "-" or " " or '\0'. */
etByte errorflag = 0; /* True if an error is encountered */
(void)errorflag;
etByte xtype; /* Conversion paradigm */
char *zExtra; /* Extra memory used for etTCLESCAPE conversions */
#ifndef SQLITE_OMIT_FLOATING_POINT

View file

@ -62,35 +62,35 @@ Select *sqlite3SelectNew(
){
Select *pNew;
Select standin;
Select *p;
sqlite3 *db = pParse->db;
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
assert( !pOffset || pLimit ); /* Can't have OFFSET without LIMIT. */
p = pNew ? pNew : &standin;
if( pNew==0 ){
pNew = &standin;
memset(pNew, 0, sizeof(*pNew));
memset(p, 0, sizeof(*p));
}
if( pEList==0 ){
pEList = sqlite3ExprListAppend(pParse, 0, sqlite3Expr(db,TK_ALL,0,0,0), 0);
}
pNew->pEList = pEList;
pNew->pSrc = pSrc;
pNew->pWhere = pWhere;
pNew->pGroupBy = pGroupBy;
pNew->pHaving = pHaving;
pNew->pOrderBy = pOrderBy;
pNew->isDistinct = isDistinct;
pNew->op = TK_SELECT;
p->pEList = pEList;
p->pSrc = pSrc;
p->pWhere = pWhere;
p->pGroupBy = pGroupBy;
p->pHaving = pHaving;
p->pOrderBy = pOrderBy;
p->isDistinct = isDistinct;
p->op = TK_SELECT;
assert( pOffset==0 || pLimit!=0 );
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
pNew->iLimit = -1;
pNew->iOffset = -1;
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
pNew->addrOpenEphm[2] = -1;
if( pNew==&standin) {
clearSelect(pNew);
pNew = 0;
p->pLimit = pLimit;
p->pOffset = pOffset;
p->iLimit = -1;
p->iOffset = -1;
p->addrOpenEphm[0] = -1;
p->addrOpenEphm[1] = -1;
p->addrOpenEphm[2] = -1;
if( pNew==0 ){
clearSelect(p);
}
return pNew;
}

View file

@ -108,10 +108,10 @@ void sqlite3Update(
int isView; /* Trying to update a view */
int triggers_exist = 0; /* True if any row triggers exist */
#endif
int iBeginAfterTrigger; /* Address of after trigger program */
int iEndAfterTrigger; /* Exit of after trigger program */
int iBeginBeforeTrigger; /* Address of before trigger program */
int iEndBeforeTrigger; /* Exit of before trigger program */
int iBeginAfterTrigger = 0; /* Address of after trigger program */
int iEndAfterTrigger = 0; /* Exit of after trigger program */
int iBeginBeforeTrigger = 0; /* Address of before trigger program */
int iEndBeforeTrigger = 0; /* Exit of before trigger program */
u32 old_col_mask = 0; /* Mask of OLD.* columns in use */
u32 new_col_mask = 0; /* Mask of NEW.* columns in use */

View file

@ -501,8 +501,8 @@ int sqlite3VdbeExec(
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
u8 encoding = ENC(db); /* The database encoding */
Mem *pIn1, *pIn2, *pIn3; /* Input operands */
Mem *pOut; /* Output operand */
Mem *pIn1 = 0, *pIn2 = 0, *pIn3 = 0; /* Input operands */
Mem *pOut = 0; /* Output operand */
u8 opProperty;
#ifdef VDBE_PROFILE
unsigned long long start; /* CPU clock count at start of opcode */
@ -1652,7 +1652,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
*/
case OP_And: /* same as TK_AND, in1, in2, out3 */
case OP_Or: { /* same as TK_OR, in1, in2, out3 */
int v1, v2; /* 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
int v1 = 0, v2 = 0; /* 0==FALSE, 1==TRUE, 2==UNKNOWN or NULL */
if( pIn1->flags & MEM_Null ){
v1 = 2;
@ -2738,7 +2738,7 @@ case OP_MoveGt: { /* jump, in3 */
pC = p->apCsr[i];
assert( pC!=0 );
if( pC->pCursor!=0 ){
int res, oc;
int res = 0, oc;
oc = pOp->opcode;
pC->nullRow = 0;
*pC->pIncrKey = oc==OP_MoveGt || oc==OP_MoveLe;
@ -3299,7 +3299,7 @@ case OP_Insert: {
*/
case OP_Delete: {
int i = pOp->p1;
i64 iKey;
i64 iKey = 0;
Cursor *pC;
assert( i>=0 && i<p->nCursor );
@ -3373,7 +3373,7 @@ case OP_RowData: { /* out2-prerelease */
int i = pOp->p1;
Cursor *pC;
BtCursor *pCrsr;
u32 n;
u32 n = 0;
/* Note that RowKey and RowData are really exactly the same instruction */
assert( i>=0 && i<p->nCursor );

View file

@ -565,6 +565,7 @@ static Mem *columnMem(sqlite3_stmt *pStmt, int i){
if( pVm && pVm->pResultSet!=0 && i<pVm->nResColumn && i>=0 ){
sqlite3_mutex_enter(pVm->db->mutex);
vals = sqlite3_data_count(pStmt);
(void)vals;
pOut = &pVm->pResultSet[i];
}else{
static const Mem nullMem = {{0}, 0.0, 0, "", 0, MEM_Null, SQLITE_NULL };

View file

@ -5,7 +5,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I../core -I../core/platform -I../widgets -I../shell -I../tasks -I../core/thirdparty
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I../core -I../core/platform -I../widgets -I../shell -I../tasks -I../core/thirdparty
OBJDIR = ../obj/taskmgr
LIBSDIR = ../bin/libs

View file

@ -5,7 +5,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586
OBJDIR = ../obj/tasks
LIBSDIR = ../bin/libs

View file

@ -6,7 +6,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I. -I../core -I../core/platform -I../tasks -I../core/thirdparty
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I. -I../core -I../core/platform -I../tasks -I../core/thirdparty
OBJDIR = ../obj/texthelp
LIBSDIR = ../bin/libs

View file

@ -4,7 +4,7 @@
# (Linux or DOS), not on the target. No cross-compilation needed.
CC = gcc
CFLAGS = -O2 -Wall -Wextra -I../core
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-format-truncation -I../core -I../core/platform
BINDIR = ../bin
@ -12,7 +12,7 @@ BINDIR = ../bin
CONFIGDIR = ../bin/config
all: $(BINDIR)/dvxres $(BINDIR)/mkicon $(BINDIR)/mktbicon $(BINDIR)/mkwgticon $(BINDIR)/bmp2raw $(CONFIGDIR)/SPLASH.RAW
all: $(BINDIR)/dvxres $(BINDIR)/mkicon $(BINDIR)/mktbicon $(BINDIR)/mkwgticon $(BINDIR)/bmp2raw $(BINDIR)/dvxhlpc $(CONFIGDIR)/SPLASH.RAW
$(BINDIR)/dvxres: dvxres.c ../core/dvxResource.c ../core/dvxResource.h | $(BINDIR)
$(CC) $(CFLAGS) -o $@ dvxres.c ../core/dvxResource.c
@ -29,6 +29,9 @@ $(BINDIR)/mkwgticon: mkwgticon.c | $(BINDIR)
$(BINDIR)/bmp2raw: bmp2raw.c | $(BINDIR)
$(CC) $(CFLAGS) -o $@ bmp2raw.c
$(BINDIR)/dvxhlpc: dvxhlpc.c ../apps/dvxhelp/hlpformat.h | $(BINDIR)
$(CC) $(CFLAGS) -o $@ dvxhlpc.c
$(CONFIGDIR)/SPLASH.RAW: $(BINDIR)/bmp2raw ../assets/splash.bmp | $(CONFIGDIR)
$(BINDIR)/bmp2raw ../assets/splash.bmp $@

1726
tools/dvxhlpc.c Normal file

File diff suppressed because it is too large Load diff

View file

@ -275,6 +275,37 @@ static void iconBasic(void) {
}
static void iconHelp(void) {
// Blue book with white "?" on it
clear(192, 192, 192);
// Book body (blue)
rect(6, 4, 20, 24, 0, 0, 180);
// Book spine (darker blue)
rect(6, 4, 3, 24, 0, 0, 130);
// Book pages (white edge)
vline(25, 5, 22, 255, 255, 255);
// Question mark in white
// Top curve
hline(14, 9, 5, 255, 255, 255);
pixel(13, 10, 255, 255, 255);
pixel(19, 10, 255, 255, 255);
pixel(19, 11, 255, 255, 255);
pixel(18, 12, 255, 255, 255);
pixel(17, 13, 255, 255, 255);
// Stem
pixel(16, 14, 255, 255, 255);
pixel(16, 15, 255, 255, 255);
pixel(16, 16, 255, 255, 255);
// Dot
pixel(16, 19, 255, 255, 255);
pixel(16, 20, 255, 255, 255);
}
static void writeBmp(const char *path) {
int32_t rowPad = (4 - (W * 3) % 4) % 4;
int32_t rowSize = W * 3 + rowPad;
@ -324,7 +355,7 @@ static void writeBmp(const char *path) {
int main(int argc, char **argv) {
if (argc < 3) {
fprintf(stderr, "Usage: mkicon <output.bmp> <type>\n");
fprintf(stderr, "Types: noicon, clock, notepad, cpanel, dvxdemo, imgview, basic\n");
fprintf(stderr, "Types: noicon, clock, notepad, cpanel, dvxdemo, imgview, basic, help\n");
return 1;
}
@ -345,6 +376,8 @@ int main(int argc, char **argv) {
iconBasic();
} else if (strcmp(type, "imgview") == 0) {
iconImgview();
} else if (strcmp(type, "help") == 0) {
iconHelp();
} else {
fprintf(stderr, "Unknown icon type: %s\n", type);
return 1;

View file

@ -6,7 +6,7 @@
DJGPP_PREFIX = $(HOME)/djgpp/djgpp
CC = $(DJGPP_PREFIX)/bin/i586-pc-msdosdjgpp-gcc
DXE3GEN = PATH=$(DJGPP_PREFIX)/bin:$(PATH) DJDIR=$(DJGPP_PREFIX)/i586-pc-msdosdjgpp $(DJGPP_PREFIX)/i586-pc-msdosdjgpp/bin/dxe3gen
CFLAGS = -O2 -Wall -Wextra -Wno-type-limits -Wno-sign-compare -march=i486 -mtune=i586 -I../core -I../core/platform -I../tasks -I../core/thirdparty
CFLAGS = -O2 -Wall -Wextra -Werror -Wno-type-limits -Wno-sign-compare -Wno-format-truncation -march=i486 -mtune=i586 -I../core -I../core/platform -I../tasks -I../core/thirdparty
DVXRES = ../bin/dvxres
OBJDIR = ../obj/widgets

View file

@ -1070,9 +1070,9 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "Cols", WGT_IFACE_INT, (void *)wgtAnsiTermGetCols, NULL },
{ "Rows", WGT_IFACE_INT, (void *)wgtAnsiTermGetRows, NULL },
{ "Scrollback", WGT_IFACE_INT, NULL, (void *)wgtAnsiTermSetScrollback }
{ "Cols", WGT_IFACE_INT, (void *)wgtAnsiTermGetCols, NULL, NULL },
{ "Rows", WGT_IFACE_INT, (void *)wgtAnsiTermGetRows, NULL, NULL },
{ "Scrollback", WGT_IFACE_INT, NULL, (void *)wgtAnsiTermSetScrollback, NULL }
};
static const WgtMethodDescT sMethods[] = {

View file

@ -252,7 +252,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "Value", WGT_IFACE_BOOL, (void *)wgtCheckboxIsChecked, (void *)wgtCheckboxSetChecked }
{ "Value", WGT_IFACE_BOOL, (void *)wgtCheckboxIsChecked, (void *)wgtCheckboxSetChecked, NULL }
};
static const WgtIfaceT sIface = {

View file

@ -538,7 +538,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "ListIndex", WGT_IFACE_INT, (void *)wgtComboBoxGetSelected, (void *)wgtComboBoxSetSelected }
{ "ListIndex", WGT_IFACE_INT, (void *)wgtComboBoxGetSelected, (void *)wgtComboBoxSetSelected, NULL }
};
static const WgtIfaceT sIface = {

View file

@ -410,7 +410,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "ListIndex", WGT_IFACE_INT, (void *)wgtDropdownGetSelected, (void *)wgtDropdownSetSelected }
{ "ListIndex", WGT_IFACE_INT, (void *)wgtDropdownGetSelected, (void *)wgtDropdownSetSelected, NULL }
};
static const WgtIfaceT sIface = {

View file

@ -289,9 +289,9 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "Picture", WGT_IFACE_STRING, NULL, (void *)wgtImageLoadFile },
{ "ImageWidth", WGT_IFACE_INT, (void *)wgtImageGetWidth, NULL },
{ "ImageHeight", WGT_IFACE_INT, (void *)wgtImageGetHeight, NULL }
{ "Picture", WGT_IFACE_STRING, NULL, (void *)wgtImageLoadFile, NULL },
{ "ImageWidth", WGT_IFACE_INT, (void *)wgtImageGetWidth, NULL, NULL },
{ "ImageHeight", WGT_IFACE_INT, (void *)wgtImageGetHeight, NULL, NULL }
};
static const WgtIfaceT sIface = {

View file

@ -360,9 +360,9 @@ static const struct {
};
static const WgtPropDescT sImgBtnProps[] = {
{ "Picture", WGT_IFACE_STRING, NULL, (void *)wgtImageButtonLoadFile },
{ "ImageWidth", WGT_IFACE_INT, (void *)wgtImageButtonGetWidth, NULL },
{ "ImageHeight", WGT_IFACE_INT, (void *)wgtImageButtonGetHeight, NULL }
{ "Picture", WGT_IFACE_STRING, NULL, (void *)wgtImageButtonLoadFile, NULL },
{ "ImageWidth", WGT_IFACE_INT, (void *)wgtImageButtonGetWidth, NULL, NULL },
{ "ImageHeight", WGT_IFACE_INT, (void *)wgtImageButtonGetHeight, NULL, NULL }
};
static const WgtIfaceT sIface = {

View file

@ -858,7 +858,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "ListIndex", WGT_IFACE_INT, (void *)wgtListBoxGetSelected, (void *)wgtListBoxSetSelected }
{ "ListIndex", WGT_IFACE_INT, (void *)wgtListBoxGetSelected, (void *)wgtListBoxSetSelected, NULL }
};
static const WgtMethodDescT sMethods[] = {

View file

@ -1738,7 +1738,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "ListIndex", WGT_IFACE_INT, (void *)wgtListViewGetSelected, (void *)wgtListViewSetSelected }
{ "ListIndex", WGT_IFACE_INT, (void *)wgtListViewGetSelected, (void *)wgtListViewSetSelected, NULL }
};
static const WgtMethodDescT sMethods[] = {

View file

@ -210,7 +210,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "Value", WGT_IFACE_INT, (void *)wgtProgressBarGetValue, (void *)wgtProgressBarSetValue }
{ "Value", WGT_IFACE_INT, (void *)wgtProgressBarGetValue, (void *)wgtProgressBarSetValue, NULL }
};
static const WgtIfaceT sIface = {

View file

@ -410,7 +410,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "Value", WGT_IFACE_INT, (void *)wgtRadioGetIndex, NULL }
{ "Value", WGT_IFACE_INT, (void *)wgtRadioGetIndex, NULL, NULL }
};
static const WgtMethodDescT sMethods[] = {

View file

@ -394,7 +394,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "Value", WGT_IFACE_INT, (void *)wgtSliderGetValue, (void *)wgtSliderSetValue }
{ "Value", WGT_IFACE_INT, (void *)wgtSliderGetValue, (void *)wgtSliderSetValue, NULL }
};
static const WgtIfaceT sIface = {

View file

@ -517,7 +517,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "Position", WGT_IFACE_INT, (void *)wgtSplitterGetPos, (void *)wgtSplitterSetPos }
{ "Position", WGT_IFACE_INT, (void *)wgtSplitterGetPos, (void *)wgtSplitterSetPos, NULL }
};
static const WgtIfaceT sIface = {

View file

@ -675,7 +675,7 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "TabIndex", WGT_IFACE_INT, (void *)wgtTabControlGetActive, (void *)wgtTabControlSetActive }
{ "TabIndex", WGT_IFACE_INT, (void *)wgtTabControlGetActive, (void *)wgtTabControlSetActive, NULL }
};
static const WgtMethodDescT sMethods[] = {

View file

@ -187,7 +187,6 @@ static void textAreaRebuildCache(WidgetT *w);
static void textAreaOffToRowCol(const char *buf, int32_t off, int32_t *row, int32_t *col);
static int32_t visualCol(const char *buf, int32_t lineStart, int32_t off, int32_t tabW);
static int32_t visualColToOff(const char *buf, int32_t len, int32_t lineStart, int32_t targetVC, int32_t tabW);
static int32_t visualLineLen(const char *buf, int32_t len, int32_t lineStart, int32_t tabW);
static void textEditSaveUndo(char *buf, int32_t len, int32_t cursor, char *undoBuf, int32_t *pUndoLen, int32_t *pUndoCursor, int32_t bufSize);
static void widgetTextAreaDragSelect(WidgetT *w, WidgetT *root, int32_t vx, int32_t vy);
static void widgetTextAreaOnDragUpdate(WidgetT *w, WidgetT *root, int32_t x, int32_t y);
@ -877,25 +876,6 @@ static int32_t visualColToOff(const char *buf, int32_t len, int32_t lineStart, i
}
// Tab-aware visual line length (in visual columns).
static int32_t visualLineLen(const char *buf, int32_t len, int32_t lineStart, int32_t tabW) {
int32_t vc = 0;
int32_t i = lineStart;
while (i < len && buf[i] != '\n') {
if (buf[i] == '\t' && tabW > 0) {
vc += tabW - (vc % tabW);
} else {
vc++;
}
i++;
}
return vc;
}
static int32_t textAreaCursorToOff(const char *buf, int32_t len, int32_t row, int32_t col) {
int32_t start = textAreaLineStart(buf, len, row);
int32_t lineL = textAreaLineLen(buf, len, row);
@ -1651,7 +1631,7 @@ void widgetTextAreaOnMouse(WidgetT *w, WidgetT *root, int32_t vx, int32_t vy) {
visCols = 1;
}
int32_t totalLines = textAreaCountLines(ta->buf, ta->len);
int32_t totalLines = textAreaGetLineCount(w);
int32_t maxScroll = totalLines - visRows;
if (maxScroll < 0) {

View file

@ -229,8 +229,8 @@ static const struct {
};
static const WgtPropDescT sProps[] = {
{ "Enabled", WGT_IFACE_BOOL, (void *)wgtTimerIsRunning, (void *)wgtTimerSetEnabled },
{ "Interval", WGT_IFACE_INT, NULL, (void *)wgtTimerSetInterval }
{ "Enabled", WGT_IFACE_BOOL, (void *)wgtTimerIsRunning, (void *)wgtTimerSetEnabled, NULL },
{ "Interval", WGT_IFACE_INT, NULL, (void *)wgtTimerSetInterval, NULL }
};
static const WgtMethodDescT sMethods[] = {