Compare commits
No commits in common. "a4727754e3c607352babae405a7f4b7ce9860ba0" and "a3e7292591ca4d81f63afee773dd538ab2a574ce" have entirely different histories.
a4727754e3
...
a3e7292591
22 changed files with 30 additions and 747 deletions
2
.gitattributes
vendored
2
.gitattributes
vendored
|
|
@ -1,4 +1,2 @@
|
||||||
*.bmp filter=lfs diff=lfs merge=lfs -text
|
*.bmp filter=lfs diff=lfs merge=lfs -text
|
||||||
*.BMP filter=lfs diff=lfs merge=lfs -text
|
*.BMP filter=lfs diff=lfs merge=lfs -text
|
||||||
*.zip filter=lfs diff=lfs merge=lfs -text
|
|
||||||
*.ZIP filter=lfs diff=lfs merge=lfs -text
|
|
||||||
|
|
|
||||||
4
Makefile
4
Makefile
|
|
@ -23,5 +23,5 @@ clean:
|
||||||
$(MAKE) -C tasks clean
|
$(MAKE) -C tasks clean
|
||||||
$(MAKE) -C dvxshell clean
|
$(MAKE) -C dvxshell clean
|
||||||
$(MAKE) -C apps clean
|
$(MAKE) -C apps clean
|
||||||
-rmdir obj/dvx/widgets obj/dvx/platform obj/dvx/thirdparty obj/dvx obj/tasks obj/dvxshell obj/apps obj 2>/dev/null
|
-rmdir obj/dvx/widgets obj/dvx/platform obj/dvx obj/tasks obj/dvxshell obj/apps obj 2>/dev/null
|
||||||
-rmdir bin/config bin/apps/progman bin/apps/notepad bin/apps/clock bin/apps/dvxdemo bin/apps bin lib 2>/dev/null
|
-rmdir bin/apps/progman bin/apps/notepad bin/apps/clock bin/apps/dvxdemo bin/apps bin lib 2>/dev/null
|
||||||
|
|
|
||||||
20
dvx.ini
20
dvx.ini
|
|
@ -1,20 +0,0 @@
|
||||||
; DVX Configuration
|
|
||||||
;
|
|
||||||
; Video mode selection. The system picks the closest available VESA mode.
|
|
||||||
; Common resolutions: 640x480, 800x600, 1024x768
|
|
||||||
; Supported color depths: 8, 15, 16, 24, 32
|
|
||||||
|
|
||||||
[video]
|
|
||||||
width = 640
|
|
||||||
height = 480
|
|
||||||
bpp = 16
|
|
||||||
|
|
||||||
; Mouse settings.
|
|
||||||
; wheel: normal or reversed
|
|
||||||
; doubleclick: double-click speed in milliseconds (200-900, default 500)
|
|
||||||
; acceleration: off, low, medium, high (default medium)
|
|
||||||
|
|
||||||
[mouse]
|
|
||||||
wheel = normal
|
|
||||||
doubleclick = 500
|
|
||||||
acceleration = medium
|
|
||||||
23
dvx/Makefile
23
dvx/Makefile
|
|
@ -10,15 +10,12 @@ CFLAGS = -O2 -Wall -Wextra -march=i486 -mtune=i586
|
||||||
OBJDIR = ../obj/dvx
|
OBJDIR = ../obj/dvx
|
||||||
WOBJDIR = ../obj/dvx/widgets
|
WOBJDIR = ../obj/dvx/widgets
|
||||||
POBJDIR = ../obj/dvx/platform
|
POBJDIR = ../obj/dvx/platform
|
||||||
TOBJDIR = ../obj/dvx/thirdparty
|
|
||||||
LIBDIR = ../lib
|
LIBDIR = ../lib
|
||||||
|
|
||||||
SRCS = dvxVideo.c dvxDraw.c dvxComp.c dvxWm.c dvxIcon.c dvxImageWrite.c dvxApp.c dvxDialog.c dvxPrefs.c
|
SRCS = dvxVideo.c dvxDraw.c dvxComp.c dvxWm.c dvxIcon.c dvxImageWrite.c dvxApp.c dvxDialog.c
|
||||||
|
|
||||||
PSRCS = platform/dvxPlatformDos.c
|
PSRCS = platform/dvxPlatformDos.c
|
||||||
|
|
||||||
TSRCS = thirdparty/ini/src/ini.c
|
|
||||||
|
|
||||||
WSRCS = widgets/widgetAnsiTerm.c \
|
WSRCS = widgets/widgetAnsiTerm.c \
|
||||||
widgets/widgetClass.c \
|
widgets/widgetClass.c \
|
||||||
widgets/widgetCore.c \
|
widgets/widgetCore.c \
|
||||||
|
|
@ -54,15 +51,14 @@ WSRCS = widgets/widgetAnsiTerm.c \
|
||||||
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
|
OBJS = $(patsubst %.c,$(OBJDIR)/%.o,$(SRCS))
|
||||||
POBJS = $(patsubst platform/%.c,$(POBJDIR)/%.o,$(PSRCS))
|
POBJS = $(patsubst platform/%.c,$(POBJDIR)/%.o,$(PSRCS))
|
||||||
WOBJS = $(patsubst widgets/%.c,$(WOBJDIR)/%.o,$(WSRCS))
|
WOBJS = $(patsubst widgets/%.c,$(WOBJDIR)/%.o,$(WSRCS))
|
||||||
TOBJS = $(TOBJDIR)/ini.o
|
|
||||||
TARGET = $(LIBDIR)/libdvx.a
|
TARGET = $(LIBDIR)/libdvx.a
|
||||||
|
|
||||||
.PHONY: all clean
|
.PHONY: all clean
|
||||||
|
|
||||||
all: $(TARGET)
|
all: $(TARGET)
|
||||||
|
|
||||||
$(TARGET): $(OBJS) $(POBJS) $(WOBJS) $(TOBJS) | $(LIBDIR)
|
$(TARGET): $(OBJS) $(POBJS) $(WOBJS) | $(LIBDIR)
|
||||||
$(AR) rcs $@ $(OBJS) $(POBJS) $(WOBJS) $(TOBJS)
|
$(AR) rcs $@ $(OBJS) $(POBJS) $(WOBJS)
|
||||||
$(RANLIB) $@
|
$(RANLIB) $@
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.c | $(OBJDIR)
|
$(OBJDIR)/%.o: %.c | $(OBJDIR)
|
||||||
|
|
@ -74,9 +70,6 @@ $(POBJDIR)/%.o: platform/%.c | $(POBJDIR)
|
||||||
$(WOBJDIR)/%.o: widgets/%.c | $(WOBJDIR)
|
$(WOBJDIR)/%.o: widgets/%.c | $(WOBJDIR)
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
$(TOBJDIR)/ini.o: thirdparty/ini/src/ini.c | $(TOBJDIR)
|
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
|
||||||
|
|
||||||
$(OBJDIR):
|
$(OBJDIR):
|
||||||
mkdir -p $(OBJDIR)
|
mkdir -p $(OBJDIR)
|
||||||
|
|
||||||
|
|
@ -86,9 +79,6 @@ $(POBJDIR):
|
||||||
$(WOBJDIR):
|
$(WOBJDIR):
|
||||||
mkdir -p $(WOBJDIR)
|
mkdir -p $(WOBJDIR)
|
||||||
|
|
||||||
$(TOBJDIR):
|
|
||||||
mkdir -p $(TOBJDIR)
|
|
||||||
|
|
||||||
$(LIBDIR):
|
$(LIBDIR):
|
||||||
mkdir -p $(LIBDIR)
|
mkdir -p $(LIBDIR)
|
||||||
|
|
||||||
|
|
@ -102,14 +92,9 @@ $(OBJDIR)/dvxImageWrite.o: dvxImageWrite.c thirdparty/stb_image_write.h
|
||||||
$(OBJDIR)/dvxApp.o: dvxApp.c dvxApp.h platform/dvxPlatform.h dvxTypes.h dvxVideo.h dvxDraw.h dvxComp.h dvxWm.h dvxFont.h dvxCursor.h
|
$(OBJDIR)/dvxApp.o: dvxApp.c dvxApp.h platform/dvxPlatform.h dvxTypes.h dvxVideo.h dvxDraw.h dvxComp.h dvxWm.h dvxFont.h dvxCursor.h
|
||||||
$(OBJDIR)/dvxDialog.o: dvxDialog.c dvxDialog.h platform/dvxPlatform.h dvxApp.h dvxWidget.h widgets/widgetInternal.h dvxTypes.h dvxDraw.h
|
$(OBJDIR)/dvxDialog.o: dvxDialog.c dvxDialog.h platform/dvxPlatform.h dvxApp.h dvxWidget.h widgets/widgetInternal.h dvxTypes.h dvxDraw.h
|
||||||
|
|
||||||
$(OBJDIR)/dvxPrefs.o: dvxPrefs.c dvxPrefs.h thirdparty/ini/src/ini.h
|
|
||||||
|
|
||||||
# Platform file dependencies
|
# Platform file dependencies
|
||||||
$(POBJDIR)/dvxPlatformDos.o: platform/dvxPlatformDos.c platform/dvxPlatform.h dvxTypes.h dvxPalette.h
|
$(POBJDIR)/dvxPlatformDos.o: platform/dvxPlatformDos.c platform/dvxPlatform.h dvxTypes.h dvxPalette.h
|
||||||
|
|
||||||
# Thirdparty file dependencies
|
|
||||||
$(TOBJDIR)/ini.o: thirdparty/ini/src/ini.c thirdparty/ini/src/ini.h
|
|
||||||
|
|
||||||
# Widget file dependencies
|
# Widget file dependencies
|
||||||
WIDGET_DEPS = widgets/widgetInternal.h dvxWidget.h dvxTypes.h dvxApp.h dvxDraw.h dvxWm.h dvxVideo.h
|
WIDGET_DEPS = widgets/widgetInternal.h dvxWidget.h dvxTypes.h dvxApp.h dvxDraw.h dvxWm.h dvxVideo.h
|
||||||
$(WOBJDIR)/widgetClass.o: widgets/widgetClass.c $(WIDGET_DEPS)
|
$(WOBJDIR)/widgetClass.o: widgets/widgetClass.c $(WIDGET_DEPS)
|
||||||
|
|
@ -145,4 +130,4 @@ $(WOBJDIR)/widgetScrollbar.o: widgets/widgetScrollbar.c $(WIDGET_DEPS)
|
||||||
$(WOBJDIR)/widgetTreeView.o: widgets/widgetTreeView.c $(WIDGET_DEPS)
|
$(WOBJDIR)/widgetTreeView.o: widgets/widgetTreeView.c $(WIDGET_DEPS)
|
||||||
|
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJS) $(POBJS) $(WOBJS) $(TOBJS) $(TARGET)
|
rm -f $(OBJS) $(POBJS) $(WOBJS) $(TARGET)
|
||||||
|
|
|
||||||
26
dvx/dvxApp.c
26
dvx/dvxApp.c
|
|
@ -1114,7 +1114,7 @@ static void dispatchEvents(AppContextT *ctx) {
|
||||||
|
|
||||||
if (sb) {
|
if (sb) {
|
||||||
int32_t oldValue = sb->value;
|
int32_t oldValue = sb->value;
|
||||||
sb->value += ctx->mouseWheel * ctx->wheelDirection * MOUSE_WHEEL_STEP;
|
sb->value += ctx->mouseWheel * MOUSE_WHEEL_STEP;
|
||||||
|
|
||||||
if (sb->value < sb->min) {
|
if (sb->value < sb->min) {
|
||||||
sb->value = sb->min;
|
sb->value = sb->min;
|
||||||
|
|
@ -1603,9 +1603,6 @@ int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_
|
||||||
ctx->lastCloseClickTime = 0;
|
ctx->lastCloseClickTime = 0;
|
||||||
ctx->lastTitleClickId = -1;
|
ctx->lastTitleClickId = -1;
|
||||||
ctx->lastTitleClickTime = 0;
|
ctx->lastTitleClickTime = 0;
|
||||||
ctx->wheelDirection = 1;
|
|
||||||
ctx->dblClickTicks = DBLCLICK_THRESHOLD;
|
|
||||||
sDblClickTicks = DBLCLICK_THRESHOLD;
|
|
||||||
|
|
||||||
// Pre-compute fixed-point 16.16 reciprocal of character height so
|
// Pre-compute fixed-point 16.16 reciprocal of character height so
|
||||||
// popup menu item index calculation can use multiply+shift instead
|
// popup menu item index calculation can use multiply+shift instead
|
||||||
|
|
@ -1887,21 +1884,6 @@ int32_t dvxScreenshot(AppContextT *ctx, const char *path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// dvxSetMouseConfig
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
void dvxSetMouseConfig(AppContextT *ctx, int32_t wheelDir, int32_t dblClickMs, int32_t accelThreshold) {
|
|
||||||
ctx->wheelDirection = (wheelDir < 0) ? -1 : 1;
|
|
||||||
ctx->dblClickTicks = (clock_t)dblClickMs * CLOCKS_PER_SEC / 1000;
|
|
||||||
sDblClickTicks = ctx->dblClickTicks;
|
|
||||||
|
|
||||||
if (accelThreshold > 0) {
|
|
||||||
platformMouseSetAccel(accelThreshold);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// dvxShutdown
|
// dvxShutdown
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -2257,7 +2239,7 @@ static void handleMouseButton(AppContextT *ctx, int32_t mx, int32_t my, int32_t
|
||||||
clock_t now = clock();
|
clock_t now = clock();
|
||||||
|
|
||||||
if (ctx->lastIconClickId == iconWin->id &&
|
if (ctx->lastIconClickId == iconWin->id &&
|
||||||
(now - ctx->lastIconClickTime) < ctx->dblClickTicks) {
|
(now - ctx->lastIconClickTime) < DBLCLICK_THRESHOLD) {
|
||||||
// Double-click: restore minimized window
|
// Double-click: restore minimized window
|
||||||
// Dirty the entire icon strip area
|
// Dirty the entire icon strip area
|
||||||
dirtyListAdd(&ctx->dirty, 0,
|
dirtyListAdd(&ctx->dirty, 0,
|
||||||
|
|
@ -2306,7 +2288,7 @@ static void handleMouseButton(AppContextT *ctx, int32_t mx, int32_t my, int32_t
|
||||||
|
|
||||||
if (win->resizable &&
|
if (win->resizable &&
|
||||||
ctx->lastTitleClickId == win->id &&
|
ctx->lastTitleClickId == win->id &&
|
||||||
(now - ctx->lastTitleClickTime) < ctx->dblClickTicks) {
|
(now - ctx->lastTitleClickTime) < DBLCLICK_THRESHOLD) {
|
||||||
// Double-click: toggle maximize/restore
|
// Double-click: toggle maximize/restore
|
||||||
ctx->lastTitleClickId = -1;
|
ctx->lastTitleClickId = -1;
|
||||||
|
|
||||||
|
|
@ -2328,7 +2310,7 @@ static void handleMouseButton(AppContextT *ctx, int32_t mx, int32_t my, int32_t
|
||||||
clock_t now = clock();
|
clock_t now = clock();
|
||||||
|
|
||||||
if (ctx->lastCloseClickId == win->id &&
|
if (ctx->lastCloseClickId == win->id &&
|
||||||
(now - ctx->lastCloseClickTime) < ctx->dblClickTicks) {
|
(now - ctx->lastCloseClickTime) < DBLCLICK_THRESHOLD) {
|
||||||
ctx->lastCloseClickId = -1;
|
ctx->lastCloseClickId = -1;
|
||||||
closeSysMenu(ctx);
|
closeSysMenu(ctx);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -92,9 +92,6 @@ typedef struct AppContextT {
|
||||||
// terminal/text widgets) becomes a multiply+shift instead of an
|
// terminal/text widgets) becomes a multiply+shift instead of an
|
||||||
// integer divide, which is very slow on 486 (40+ cycles per DIV).
|
// integer divide, which is very slow on 486 (40+ cycles per DIV).
|
||||||
uint32_t charHeightRecip; // fixed-point 16.16 reciprocal of font.charHeight
|
uint32_t charHeightRecip; // fixed-point 16.16 reciprocal of font.charHeight
|
||||||
// Mouse configuration (loaded from preferences)
|
|
||||||
int32_t wheelDirection; // 1 = normal, -1 = reversed
|
|
||||||
clock_t dblClickTicks; // double-click speed in clock() ticks
|
|
||||||
} AppContextT;
|
} AppContextT;
|
||||||
|
|
||||||
// Initialize the entire GUI stack: video mode, input devices, font,
|
// Initialize the entire GUI stack: video mode, input devices, font,
|
||||||
|
|
@ -102,11 +99,6 @@ typedef struct AppContextT {
|
||||||
// entry point for starting a DVX application. Returns 0 on success.
|
// entry point for starting a DVX application. Returns 0 on success.
|
||||||
int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);
|
int32_t dvxInit(AppContextT *ctx, int32_t requestedW, int32_t requestedH, int32_t preferredBpp);
|
||||||
|
|
||||||
// Configure mouse behaviour. wheelDir: 1 = normal, -1 = reversed.
|
|
||||||
// dblClickMs: double-click speed in milliseconds (e.g. 500).
|
|
||||||
// accelThreshold: double-speed threshold in mickeys/sec (0 = don't change).
|
|
||||||
void dvxSetMouseConfig(AppContextT *ctx, int32_t wheelDir, int32_t dblClickMs, int32_t accelThreshold);
|
|
||||||
|
|
||||||
// Tear down the GUI stack in reverse order: destroy all windows, restore
|
// Tear down the GUI stack in reverse order: destroy all windows, restore
|
||||||
// text mode, release input devices. Safe to call after a failed dvxInit().
|
// text mode, release input devices. Safe to call after a failed dvxInit().
|
||||||
void dvxShutdown(AppContextT *ctx);
|
void dvxShutdown(AppContextT *ctx);
|
||||||
|
|
|
||||||
101
dvx/dvxPrefs.c
101
dvx/dvxPrefs.c
|
|
@ -1,101 +0,0 @@
|
||||||
// dvxPrefs.c — INI-based preferences system
|
|
||||||
//
|
|
||||||
// Thin wrapper around rxi/ini that adds typed accessors with defaults.
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "dvxPrefs.h"
|
|
||||||
#include "thirdparty/ini/src/ini.h"
|
|
||||||
|
|
||||||
|
|
||||||
static ini_t *sIni = NULL;
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// prefsFree
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
void prefsFree(void) {
|
|
||||||
if (sIni) {
|
|
||||||
ini_free(sIni);
|
|
||||||
sIni = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// prefsGetBool
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
bool prefsGetBool(const char *section, const char *key, bool defaultVal) {
|
|
||||||
const char *val = prefsGetString(section, key, NULL);
|
|
||||||
|
|
||||||
if (!val) {
|
|
||||||
return defaultVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Case-insensitive first character check covers true/yes/1 and false/no/0
|
|
||||||
char c = (char)tolower((unsigned char)val[0]);
|
|
||||||
|
|
||||||
if (c == 't' || c == 'y' || c == '1') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (c == 'f' || c == 'n' || c == '0') {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return defaultVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// prefsGetInt
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
int32_t prefsGetInt(const char *section, const char *key, int32_t defaultVal) {
|
|
||||||
const char *val = prefsGetString(section, key, NULL);
|
|
||||||
|
|
||||||
if (!val) {
|
|
||||||
return defaultVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *end = NULL;
|
|
||||||
long n = strtol(val, &end, 10);
|
|
||||||
|
|
||||||
if (end == val) {
|
|
||||||
return defaultVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
return (int32_t)n;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// prefsGetString
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
const char *prefsGetString(const char *section, const char *key, const char *defaultVal) {
|
|
||||||
if (!sIni) {
|
|
||||||
return defaultVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *val = ini_get(sIni, section, key);
|
|
||||||
|
|
||||||
return val ? val : defaultVal;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// prefsLoad
|
|
||||||
// ============================================================
|
|
||||||
|
|
||||||
bool prefsLoad(const char *filename) {
|
|
||||||
prefsFree();
|
|
||||||
|
|
||||||
sIni = ini_load(filename);
|
|
||||||
|
|
||||||
return sIni != NULL;
|
|
||||||
}
|
|
||||||
|
|
@ -1,37 +0,0 @@
|
||||||
// dvxPrefs.h — INI-based preferences system
|
|
||||||
//
|
|
||||||
// Loads a configuration file at startup and provides typed accessors
|
|
||||||
// with caller-supplied defaults. The INI file is read-only at runtime;
|
|
||||||
// values are queried by section + key. If the file is missing or a key
|
|
||||||
// is absent, the default is returned silently.
|
|
||||||
//
|
|
||||||
// The underlying parser is rxi/ini (thirdparty/ini/src).
|
|
||||||
|
|
||||||
#ifndef DVX_PREFS_H
|
|
||||||
#define DVX_PREFS_H
|
|
||||||
|
|
||||||
#include <stdbool.h>
|
|
||||||
#include <stdint.h>
|
|
||||||
|
|
||||||
// Load an INI file into memory. Returns true on success, false if the
|
|
||||||
// file could not be opened (all getters will return their defaults).
|
|
||||||
// Only one file may be loaded at a time; calling again frees the previous.
|
|
||||||
bool prefsLoad(const char *filename);
|
|
||||||
|
|
||||||
// Release all memory held by the loaded INI file.
|
|
||||||
void prefsFree(void);
|
|
||||||
|
|
||||||
// Retrieve a string value. Returns defaultVal if the section/key pair
|
|
||||||
// is not present. The returned pointer is valid until prefsFree().
|
|
||||||
const char *prefsGetString(const char *section, const char *key, const char *defaultVal);
|
|
||||||
|
|
||||||
// Retrieve an integer value. Returns defaultVal if the section/key pair
|
|
||||||
// is not present or cannot be parsed.
|
|
||||||
int32_t prefsGetInt(const char *section, const char *key, int32_t defaultVal);
|
|
||||||
|
|
||||||
// Retrieve a boolean value. Recognises "true", "yes", "1" as true and
|
|
||||||
// "false", "no", "0" as false (case-insensitive). Returns defaultVal
|
|
||||||
// for anything else or if the key is missing.
|
|
||||||
bool prefsGetBool(const char *section, const char *key, bool defaultVal);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -139,11 +139,6 @@ bool platformMouseWheelInit(void);
|
||||||
// driver between polls).
|
// driver between polls).
|
||||||
int32_t platformMouseWheelPoll(void);
|
int32_t platformMouseWheelPoll(void);
|
||||||
|
|
||||||
// Set the double-speed threshold in mickeys/second. When the mouse
|
|
||||||
// moves faster than this, cursor movement is doubled by the driver.
|
|
||||||
// A very high value (e.g. 10000) effectively disables acceleration.
|
|
||||||
void platformMouseSetAccel(int32_t threshold);
|
|
||||||
|
|
||||||
// Move the mouse cursor to an absolute screen position. Uses INT 33h
|
// Move the mouse cursor to an absolute screen position. Uses INT 33h
|
||||||
// function 04h on DOS, SDL_WarpMouseInWindow on Linux. Used to clamp
|
// function 04h on DOS, SDL_WarpMouseInWindow on Linux. Used to clamp
|
||||||
// the cursor to window edges during resize operations.
|
// the cursor to window edges during resize operations.
|
||||||
|
|
@ -200,14 +195,4 @@ const char *platformGetSystemInfo(const DisplayT *display);
|
||||||
// describing why it's invalid. Used by the file dialog's save-as validation.
|
// describing why it's invalid. Used by the file dialog's save-as validation.
|
||||||
const char *platformValidateFilename(const char *name);
|
const char *platformValidateFilename(const char *name);
|
||||||
|
|
||||||
// Change the working directory, including drive letter on DOS. Standard
|
|
||||||
// chdir() does not switch drives under DJGPP; this wrapper calls setdisk()
|
|
||||||
// first when the path contains a drive prefix (e.g. "A:\DVX").
|
|
||||||
void platformChdir(const char *path);
|
|
||||||
|
|
||||||
// Return a pointer to the last directory separator in path, or NULL if
|
|
||||||
// none is found. On DOS this checks both '/' and '\\' since DJGPP
|
|
||||||
// accepts either. On other platforms only '/' is recognised.
|
|
||||||
char *platformPathDirEnd(const char *path);
|
|
||||||
|
|
||||||
#endif // DVX_PLATFORM_H
|
#endif // DVX_PLATFORM_H
|
||||||
|
|
|
||||||
|
|
@ -29,14 +29,12 @@
|
||||||
#include "dvxPlatform.h"
|
#include "dvxPlatform.h"
|
||||||
#include "../dvxPalette.h"
|
#include "../dvxPalette.h"
|
||||||
|
|
||||||
#include <ctype.h>
|
|
||||||
#include <dir.h>
|
|
||||||
#include <signal.h>
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <ctype.h>
|
||||||
|
#include <signal.h>
|
||||||
|
|
||||||
// DJGPP-specific headers — this is the ONLY file that includes these
|
// DJGPP-specific headers — this is the ONLY file that includes these
|
||||||
#include <dpmi.h>
|
#include <dpmi.h>
|
||||||
|
|
@ -477,24 +475,6 @@ char platformAltScanToChar(int32_t scancode) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// platformChdir
|
|
||||||
// ============================================================
|
|
||||||
//
|
|
||||||
// Changes the working directory, switching the active DOS drive first
|
|
||||||
// when the path contains a drive letter (e.g. "A:\DVX"). Standard
|
|
||||||
// chdir() under DJGPP only changes the directory on the current drive.
|
|
||||||
|
|
||||||
void platformChdir(const char *path) {
|
|
||||||
if (path[0] && path[1] == ':') {
|
|
||||||
int drive = toupper((unsigned char)path[0]) - 'A';
|
|
||||||
setdisk(drive);
|
|
||||||
}
|
|
||||||
|
|
||||||
chdir(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// platformFlushRect
|
// platformFlushRect
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -1150,25 +1130,6 @@ void platformMouseInit(int32_t screenW, int32_t screenH) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// platformMouseSetAccel
|
|
||||||
// ============================================================
|
|
||||||
//
|
|
||||||
// Sets the double-speed threshold via INT 33h function 13h. When the
|
|
||||||
// mouse moves faster than this many mickeys per second, cursor movement
|
|
||||||
// is doubled. A very high value (e.g. 10000) effectively disables
|
|
||||||
// acceleration. Typical driver defaults are around 64 mickeys/sec.
|
|
||||||
|
|
||||||
void platformMouseSetAccel(int32_t threshold) {
|
|
||||||
__dpmi_regs r;
|
|
||||||
|
|
||||||
memset(&r, 0, sizeof(r));
|
|
||||||
r.x.ax = 0x0013;
|
|
||||||
r.x.dx = threshold;
|
|
||||||
__dpmi_int(0x33, &r);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// platformMousePoll
|
// platformMousePoll
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
@ -1257,25 +1218,6 @@ void platformMouseWarp(int32_t x, int32_t y) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
|
||||||
// platformPathDirEnd
|
|
||||||
// ============================================================
|
|
||||||
//
|
|
||||||
// Returns a pointer to the last directory separator in path. DOS
|
|
||||||
// accepts both '/' and '\\', so we check for whichever appears last.
|
|
||||||
|
|
||||||
char *platformPathDirEnd(const char *path) {
|
|
||||||
char *fwd = strrchr(path, '/');
|
|
||||||
char *back = strrchr(path, '\\');
|
|
||||||
|
|
||||||
if (back > fwd) {
|
|
||||||
return back;
|
|
||||||
}
|
|
||||||
|
|
||||||
return fwd;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// ============================================================
|
// ============================================================
|
||||||
// platformSpanCopy8
|
// platformSpanCopy8
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
|
||||||
20
dvx/thirdparty/ini/LICENSE
vendored
20
dvx/thirdparty/ini/LICENSE
vendored
|
|
@ -1,20 +0,0 @@
|
||||||
Copyright (c) 2016 rxi
|
|
||||||
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
|
||||||
this software and associated documentation files (the "Software"), to deal in
|
|
||||||
the Software without restriction, including without limitation the rights to
|
|
||||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
|
||||||
of the Software, and to permit persons to whom the Software is furnished to do
|
|
||||||
so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
63
dvx/thirdparty/ini/README.md
vendored
63
dvx/thirdparty/ini/README.md
vendored
|
|
@ -1,63 +0,0 @@
|
||||||
|
|
||||||
# ini
|
|
||||||
A *tiny* ANSI C library for loading .ini config files
|
|
||||||
|
|
||||||
## Usage
|
|
||||||
The files **[ini.c](src/ini.c?raw=1)** and **[ini.h](src/ini.h?raw=1)** should
|
|
||||||
be dropped into an existing project.
|
|
||||||
|
|
||||||
The library has support for sections, comment lines and quoted string values
|
|
||||||
(with escapes). Unquoted values and keys are trimmed of whitespace when loaded.
|
|
||||||
|
|
||||||
```ini
|
|
||||||
; last modified 1 April 2001 by John Doe
|
|
||||||
[owner]
|
|
||||||
name = John Doe
|
|
||||||
organization = Acme Widgets Inc.
|
|
||||||
|
|
||||||
[database]
|
|
||||||
; use IP address in case network name resolution is not working
|
|
||||||
server = 192.0.2.62
|
|
||||||
port = 143
|
|
||||||
file = "payroll.dat"
|
|
||||||
```
|
|
||||||
|
|
||||||
An ini file can be loaded into memory by using the `ini_load()` function.
|
|
||||||
`NULL` is returned if the file cannot be loaded.
|
|
||||||
```c
|
|
||||||
ini_t *config = ini_load("config.ini");
|
|
||||||
```
|
|
||||||
|
|
||||||
The library provides two functions for retrieving values: the first is
|
|
||||||
`ini_get()`. Given a section and a key the corresponding value is returned if
|
|
||||||
it exists. If the `section` argument is `NULL` then all sections are searched.
|
|
||||||
```c
|
|
||||||
const char *name = ini_get(config, "owner", "name");
|
|
||||||
if (name) {
|
|
||||||
printf("name: %s\n", name);
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
The second, `ini_sget()`, takes the same arguments as `ini_get()` with the
|
|
||||||
addition of a scanf format string and a pointer for where to store the value.
|
|
||||||
```c
|
|
||||||
const char *server = "default";
|
|
||||||
int port = 80;
|
|
||||||
|
|
||||||
ini_sget(config, "database", "server", NULL, &server);
|
|
||||||
ini_sget(config, "database", "port", "%d", &port);
|
|
||||||
|
|
||||||
printf("server: %s:%d\n", server, port);
|
|
||||||
```
|
|
||||||
|
|
||||||
The `ini_free()` function is used to free the memory used by the `ini_t*`
|
|
||||||
object when we are done with it. Calling this function invalidates all string
|
|
||||||
pointers returned by the library.
|
|
||||||
```c
|
|
||||||
ini_free(config);
|
|
||||||
```
|
|
||||||
|
|
||||||
|
|
||||||
## License
|
|
||||||
This library is free software; you can redistribute it and/or modify it under
|
|
||||||
the terms of the MIT license. See [LICENSE](LICENSE) for details.
|
|
||||||
274
dvx/thirdparty/ini/src/ini.c
vendored
274
dvx/thirdparty/ini/src/ini.c
vendored
|
|
@ -1,274 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2016 rxi
|
|
||||||
*
|
|
||||||
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
* of this software and associated documentation files (the "Software"), to deal
|
|
||||||
* in the Software without restriction, including without limitation the rights
|
|
||||||
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
* copies of the Software, and to permit persons to whom the Software is
|
|
||||||
* furnished to do so, subject to the following conditions:
|
|
||||||
*
|
|
||||||
* The above copyright notice and this permission notice shall be included in
|
|
||||||
* all copies or substantial portions of the Software.
|
|
||||||
*
|
|
||||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
* SOFTWARE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdio.h>
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
|
||||||
#include <ctype.h>
|
|
||||||
|
|
||||||
#include "ini.h"
|
|
||||||
|
|
||||||
struct ini_t {
|
|
||||||
char *data;
|
|
||||||
char *end;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/* Case insensitive string compare */
|
|
||||||
static int strcmpci(const char *a, const char *b) {
|
|
||||||
for (;;) {
|
|
||||||
int d = tolower(*a) - tolower(*b);
|
|
||||||
if (d != 0 || !*a) {
|
|
||||||
return d;
|
|
||||||
}
|
|
||||||
a++, b++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Returns the next string in the split data */
|
|
||||||
static char* next(ini_t *ini, char *p) {
|
|
||||||
p += strlen(p);
|
|
||||||
while (p < ini->end && *p == '\0') {
|
|
||||||
p++;
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void trim_back(ini_t *ini, char *p) {
|
|
||||||
while (p >= ini->data && (*p == ' ' || *p == '\t' || *p == '\r')) {
|
|
||||||
*p-- = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static char* discard_line(ini_t *ini, char *p) {
|
|
||||||
while (p < ini->end && *p != '\n') {
|
|
||||||
*p++ = '\0';
|
|
||||||
}
|
|
||||||
return p;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
static char *unescape_quoted_value(ini_t *ini, char *p) {
|
|
||||||
/* Use `q` as write-head and `p` as read-head, `p` is always ahead of `q`
|
|
||||||
* as escape sequences are always larger than their resultant data */
|
|
||||||
char *q = p;
|
|
||||||
p++;
|
|
||||||
while (p < ini->end && *p != '"' && *p != '\r' && *p != '\n') {
|
|
||||||
if (*p == '\\') {
|
|
||||||
/* Handle escaped char */
|
|
||||||
p++;
|
|
||||||
switch (*p) {
|
|
||||||
default : *q = *p; break;
|
|
||||||
case 'r' : *q = '\r'; break;
|
|
||||||
case 'n' : *q = '\n'; break;
|
|
||||||
case 't' : *q = '\t'; break;
|
|
||||||
case '\r' :
|
|
||||||
case '\n' :
|
|
||||||
case '\0' : goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Handle normal char */
|
|
||||||
*q = *p;
|
|
||||||
}
|
|
||||||
q++, p++;
|
|
||||||
}
|
|
||||||
end:
|
|
||||||
return q;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Splits data in place into strings containing section-headers, keys and
|
|
||||||
* values using one or more '\0' as a delimiter. Unescapes quoted values */
|
|
||||||
static void split_data(ini_t *ini) {
|
|
||||||
char *value_start, *line_start;
|
|
||||||
char *p = ini->data;
|
|
||||||
|
|
||||||
while (p < ini->end) {
|
|
||||||
switch (*p) {
|
|
||||||
case '\r':
|
|
||||||
case '\n':
|
|
||||||
case '\t':
|
|
||||||
case ' ':
|
|
||||||
*p = '\0';
|
|
||||||
/* Fall through */
|
|
||||||
|
|
||||||
case '\0':
|
|
||||||
p++;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case '[':
|
|
||||||
p += strcspn(p, "]\n");
|
|
||||||
*p = '\0';
|
|
||||||
break;
|
|
||||||
|
|
||||||
case ';':
|
|
||||||
p = discard_line(ini, p);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
line_start = p;
|
|
||||||
p += strcspn(p, "=\n");
|
|
||||||
|
|
||||||
/* Is line missing a '='? */
|
|
||||||
if (*p != '=') {
|
|
||||||
p = discard_line(ini, line_start);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
trim_back(ini, p - 1);
|
|
||||||
|
|
||||||
/* Replace '=' and whitespace after it with '\0' */
|
|
||||||
do {
|
|
||||||
*p++ = '\0';
|
|
||||||
} while (*p == ' ' || *p == '\r' || *p == '\t');
|
|
||||||
|
|
||||||
/* Is a value after '=' missing? */
|
|
||||||
if (*p == '\n' || *p == '\0') {
|
|
||||||
p = discard_line(ini, line_start);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (*p == '"') {
|
|
||||||
/* Handle quoted string value */
|
|
||||||
value_start = p;
|
|
||||||
p = unescape_quoted_value(ini, p);
|
|
||||||
|
|
||||||
/* Was the string empty? */
|
|
||||||
if (p == value_start) {
|
|
||||||
p = discard_line(ini, line_start);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Discard the rest of the line after the string value */
|
|
||||||
p = discard_line(ini, p);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Handle normal value */
|
|
||||||
p += strcspn(p, "\n");
|
|
||||||
trim_back(ini, p - 1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
ini_t* ini_load(const char *filename) {
|
|
||||||
ini_t *ini = NULL;
|
|
||||||
FILE *fp = NULL;
|
|
||||||
int n, sz;
|
|
||||||
|
|
||||||
/* Init ini struct */
|
|
||||||
ini = malloc(sizeof(*ini));
|
|
||||||
if (!ini) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
memset(ini, 0, sizeof(*ini));
|
|
||||||
|
|
||||||
/* Open file */
|
|
||||||
fp = fopen(filename, "rb");
|
|
||||||
if (!fp) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Get file size */
|
|
||||||
fseek(fp, 0, SEEK_END);
|
|
||||||
sz = ftell(fp);
|
|
||||||
rewind(fp);
|
|
||||||
|
|
||||||
/* Load file content into memory, null terminate, init end var */
|
|
||||||
ini->data = malloc(sz + 1);
|
|
||||||
ini->data[sz] = '\0';
|
|
||||||
ini->end = ini->data + sz;
|
|
||||||
n = fread(ini->data, 1, sz, fp);
|
|
||||||
if (n != sz) {
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Prepare data */
|
|
||||||
split_data(ini);
|
|
||||||
|
|
||||||
/* Clean up and return */
|
|
||||||
fclose(fp);
|
|
||||||
return ini;
|
|
||||||
|
|
||||||
fail:
|
|
||||||
if (fp) fclose(fp);
|
|
||||||
if (ini) ini_free(ini);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void ini_free(ini_t *ini) {
|
|
||||||
free(ini->data);
|
|
||||||
free(ini);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
const char* ini_get(ini_t *ini, const char *section, const char *key) {
|
|
||||||
char *current_section = "";
|
|
||||||
char *val;
|
|
||||||
char *p = ini->data;
|
|
||||||
|
|
||||||
if (*p == '\0') {
|
|
||||||
p = next(ini, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
while (p < ini->end) {
|
|
||||||
if (*p == '[') {
|
|
||||||
/* Handle section */
|
|
||||||
current_section = p + 1;
|
|
||||||
|
|
||||||
} else {
|
|
||||||
/* Handle key */
|
|
||||||
val = next(ini, p);
|
|
||||||
if (!section || !strcmpci(section, current_section)) {
|
|
||||||
if (!strcmpci(p, key)) {
|
|
||||||
return val;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
p = val;
|
|
||||||
}
|
|
||||||
|
|
||||||
p = next(ini, p);
|
|
||||||
}
|
|
||||||
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
int ini_sget(
|
|
||||||
ini_t *ini, const char *section, const char *key,
|
|
||||||
const char *scanfmt, void *dst
|
|
||||||
) {
|
|
||||||
const char *val = ini_get(ini, section, key);
|
|
||||||
if (!val) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
if (scanfmt) {
|
|
||||||
sscanf(val, scanfmt, dst);
|
|
||||||
} else {
|
|
||||||
*((const char**) dst) = val;
|
|
||||||
}
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
20
dvx/thirdparty/ini/src/ini.h
vendored
20
dvx/thirdparty/ini/src/ini.h
vendored
|
|
@ -1,20 +0,0 @@
|
||||||
/**
|
|
||||||
* Copyright (c) 2016 rxi
|
|
||||||
*
|
|
||||||
* This library is free software; you can redistribute it and/or modify it
|
|
||||||
* under the terms of the MIT license. See `ini.c` for details.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INI_H
|
|
||||||
#define INI_H
|
|
||||||
|
|
||||||
#define INI_VERSION "0.1.1"
|
|
||||||
|
|
||||||
typedef struct ini_t ini_t;
|
|
||||||
|
|
||||||
ini_t* ini_load(const char *filename);
|
|
||||||
void ini_free(ini_t *ini);
|
|
||||||
const char* ini_get(ini_t *ini, const char *section, const char *key);
|
|
||||||
int ini_sget(ini_t *ini, const char *section, const char *key, const char *scanfmt, void *dst);
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -37,7 +37,6 @@
|
||||||
// otherwise dangling pointers would cause crashes. widgetDestroyChildren()
|
// otherwise dangling pointers would cause crashes. widgetDestroyChildren()
|
||||||
// and wgtDestroy() handle this cleanup.
|
// and wgtDestroy() handle this cleanup.
|
||||||
|
|
||||||
clock_t sDblClickTicks = 0; // set from ctx->dblClickTicks during first paint
|
|
||||||
bool sDebugLayout = false;
|
bool sDebugLayout = false;
|
||||||
WidgetT *sFocusedWidget = NULL; // currently focused widget (O(1) access, avoids tree walk)
|
WidgetT *sFocusedWidget = NULL; // currently focused widget (O(1) access, avoids tree walk)
|
||||||
WidgetT *sOpenPopup = NULL; // dropdown/combobox with open popup list
|
WidgetT *sOpenPopup = NULL; // dropdown/combobox with open popup list
|
||||||
|
|
|
||||||
|
|
@ -174,7 +174,6 @@ static inline void drawTextAccelEmbossed(DisplayT *d, const BlitOpsT *ops, const
|
||||||
// and only one mouse can exist, this is safe.
|
// and only one mouse can exist, this is safe.
|
||||||
|
|
||||||
extern bool sCursorBlinkOn; // text cursor blink phase (toggled by wgtUpdateCursorBlink)
|
extern bool sCursorBlinkOn; // text cursor blink phase (toggled by wgtUpdateCursorBlink)
|
||||||
extern clock_t sDblClickTicks; // double-click threshold (set from AppContextT.dblClickTicks)
|
|
||||||
extern bool sDebugLayout;
|
extern bool sDebugLayout;
|
||||||
extern WidgetT *sClosedPopup; // popup that was just closed (prevents immediate reopen)
|
extern WidgetT *sClosedPopup; // popup that was just closed (prevents immediate reopen)
|
||||||
extern WidgetT *sFocusedWidget; // currently focused widget across all windows
|
extern WidgetT *sFocusedWidget; // currently focused widget across all windows
|
||||||
|
|
|
||||||
|
|
@ -321,7 +321,7 @@ static int32_t sClickCount = 0;
|
||||||
int32_t multiClickDetect(int32_t vx, int32_t vy) {
|
int32_t multiClickDetect(int32_t vx, int32_t vy) {
|
||||||
clock_t now = clock();
|
clock_t now = clock();
|
||||||
|
|
||||||
if ((now - sLastClickTime) < sDblClickTicks &&
|
if ((now - sLastClickTime) < DBLCLICK_TICKS &&
|
||||||
abs(vx - sLastClickX) < 4 && abs(vy - sLastClickY) < 4) {
|
abs(vx - sLastClickX) < 4 && abs(vy - sLastClickY) < 4) {
|
||||||
sClickCount++;
|
sClickCount++;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,6 @@ LDFLAGS = -L../lib -ldvx -ltasks -lm
|
||||||
|
|
||||||
OBJDIR = ../obj/dvxshell
|
OBJDIR = ../obj/dvxshell
|
||||||
BINDIR = ../bin
|
BINDIR = ../bin
|
||||||
CONFIGDIR = ../bin/config
|
|
||||||
LIBDIR = ../lib
|
LIBDIR = ../lib
|
||||||
|
|
||||||
SRCS = shellMain.c shellApp.c shellExport.c shellInfo.c
|
SRCS = shellMain.c shellApp.c shellExport.c shellInfo.c
|
||||||
|
|
@ -19,7 +18,7 @@ TARGET = $(BINDIR)/dvx.exe
|
||||||
|
|
||||||
.PHONY: all clean libs
|
.PHONY: all clean libs
|
||||||
|
|
||||||
all: libs $(TARGET) $(CONFIGDIR)/dvx.ini
|
all: libs $(TARGET)
|
||||||
|
|
||||||
libs:
|
libs:
|
||||||
$(MAKE) -C ../dvx
|
$(MAKE) -C ../dvx
|
||||||
|
|
@ -31,9 +30,6 @@ $(TARGET): $(OBJS) $(LIBDIR)/libdvx.a $(LIBDIR)/libtasks.a | $(BINDIR)
|
||||||
cat $(CWSDSTUB) $(BINDIR)/dvx > $@
|
cat $(CWSDSTUB) $(BINDIR)/dvx > $@
|
||||||
rm -f $(BINDIR)/dvx
|
rm -f $(BINDIR)/dvx
|
||||||
|
|
||||||
$(CONFIGDIR)/dvx.ini: ../dvx.ini | $(CONFIGDIR)
|
|
||||||
cp $< $@
|
|
||||||
|
|
||||||
$(OBJDIR)/%.o: %.c | $(OBJDIR)
|
$(OBJDIR)/%.o: %.c | $(OBJDIR)
|
||||||
$(CC) $(CFLAGS) -c -o $@ $<
|
$(CC) $(CFLAGS) -c -o $@ $<
|
||||||
|
|
||||||
|
|
@ -43,9 +39,6 @@ $(OBJDIR):
|
||||||
$(BINDIR):
|
$(BINDIR):
|
||||||
mkdir -p $(BINDIR)
|
mkdir -p $(BINDIR)
|
||||||
|
|
||||||
$(CONFIGDIR):
|
|
||||||
mkdir -p $(CONFIGDIR)
|
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
$(OBJDIR)/shellMain.o: shellMain.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../tasks/taskswitch.h
|
$(OBJDIR)/shellMain.o: shellMain.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../tasks/taskswitch.h
|
||||||
$(OBJDIR)/shellApp.o: shellApp.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../tasks/taskswitch.h
|
$(OBJDIR)/shellApp.o: shellApp.c shellApp.h ../dvx/dvxApp.h ../dvx/dvxDialog.h ../tasks/taskswitch.h
|
||||||
|
|
@ -53,4 +46,3 @@ $(OBJDIR)/shellExport.o: shellExport.c shellApp.h shellInfo.h ../dvx/dvxApp.h .
|
||||||
$(OBJDIR)/shellInfo.o: shellInfo.c shellInfo.h shellApp.h ../dvx/dvxApp.h ../dvx/platform/dvxPlatform.h
|
$(OBJDIR)/shellInfo.o: shellInfo.c shellInfo.h shellApp.h ../dvx/dvxApp.h ../dvx/platform/dvxPlatform.h
|
||||||
clean:
|
clean:
|
||||||
rm -f $(OBJS) $(TARGET) $(BINDIR)/dvx.map $(BINDIR)/dvx.log
|
rm -f $(OBJS) $(TARGET) $(BINDIR)/dvx.map $(BINDIR)/dvx.log
|
||||||
rm -rf $(CONFIGDIR)
|
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,6 @@
|
||||||
|
|
||||||
#include "shellApp.h"
|
#include "shellApp.h"
|
||||||
#include "dvxDialog.h"
|
#include "dvxDialog.h"
|
||||||
#include "platform/dvxPlatform.h"
|
|
||||||
|
|
||||||
#include <dlfcn.h>
|
#include <dlfcn.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
|
@ -364,15 +363,21 @@ int32_t shellLoadApp(AppContextT *ctx, const char *path) {
|
||||||
app->dxeCtx.shellCtx = ctx;
|
app->dxeCtx.shellCtx = ctx;
|
||||||
app->dxeCtx.appId = id;
|
app->dxeCtx.appId = id;
|
||||||
|
|
||||||
// Derive app directory from path (everything up to the last separator).
|
// Derive app directory from path (everything up to last '/' or '\').
|
||||||
// This lets apps load resources relative to their own location rather
|
// This lets apps load resources relative to their own location rather
|
||||||
// than the shell's working directory.
|
// than the shell's working directory. Handles both Unix and DOS path
|
||||||
|
// separators because DJGPP accepts either.
|
||||||
snprintf(app->dxeCtx.appDir, sizeof(app->dxeCtx.appDir), "%s", path);
|
snprintf(app->dxeCtx.appDir, sizeof(app->dxeCtx.appDir), "%s", path);
|
||||||
|
|
||||||
char *sep = platformPathDirEnd(app->dxeCtx.appDir);
|
char *lastSlash = strrchr(app->dxeCtx.appDir, '/');
|
||||||
|
char *lastBack = strrchr(app->dxeCtx.appDir, '\\');
|
||||||
|
|
||||||
if (sep) {
|
if (lastBack > lastSlash) {
|
||||||
*sep = '\0';
|
lastSlash = lastBack;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lastSlash) {
|
||||||
|
*lastSlash = '\0';
|
||||||
} else {
|
} else {
|
||||||
app->dxeCtx.appDir[0] = '.';
|
app->dxeCtx.appDir[0] = '.';
|
||||||
app->dxeCtx.appDir[1] = '\0';
|
app->dxeCtx.appDir[1] = '\0';
|
||||||
|
|
|
||||||
|
|
@ -33,7 +33,6 @@
|
||||||
#include "dvxDialog.h"
|
#include "dvxDialog.h"
|
||||||
#include "dvxWidget.h"
|
#include "dvxWidget.h"
|
||||||
#include "dvxDraw.h"
|
#include "dvxDraw.h"
|
||||||
#include "dvxPrefs.h"
|
|
||||||
#include "dvxVideo.h"
|
#include "dvxVideo.h"
|
||||||
#include "dvxWm.h"
|
#include "dvxWm.h"
|
||||||
#include "taskswitch.h"
|
#include "taskswitch.h"
|
||||||
|
|
@ -144,14 +143,8 @@ DXE_EXPORT_TABLE(shellExportTable)
|
||||||
{ "_dvxCreateWindow", (void *)shellWrapCreateWindow },
|
{ "_dvxCreateWindow", (void *)shellWrapCreateWindow },
|
||||||
{ "_dvxDestroyWindow", (void *)shellWrapDestroyWindow },
|
{ "_dvxDestroyWindow", (void *)shellWrapDestroyWindow },
|
||||||
|
|
||||||
// dvxPrefs.h — preferences
|
|
||||||
DXE_EXPORT(prefsGetBool)
|
|
||||||
DXE_EXPORT(prefsGetInt)
|
|
||||||
DXE_EXPORT(prefsGetString)
|
|
||||||
|
|
||||||
// dvxApp.h — direct exports
|
// dvxApp.h — direct exports
|
||||||
DXE_EXPORT(dvxInit)
|
DXE_EXPORT(dvxInit)
|
||||||
DXE_EXPORT(dvxSetMouseConfig)
|
|
||||||
DXE_EXPORT(dvxShutdown)
|
DXE_EXPORT(dvxShutdown)
|
||||||
DXE_EXPORT(dvxUpdate)
|
DXE_EXPORT(dvxUpdate)
|
||||||
{ "_dvxCreateWindowCentered", (void *)shellWrapCreateWindowCentered },
|
{ "_dvxCreateWindowCentered", (void *)shellWrapCreateWindowCentered },
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,6 @@
|
||||||
#include "shellApp.h"
|
#include "shellApp.h"
|
||||||
#include "shellInfo.h"
|
#include "shellInfo.h"
|
||||||
#include "dvxDialog.h"
|
#include "dvxDialog.h"
|
||||||
#include "dvxPrefs.h"
|
|
||||||
#include "platform/dvxPlatform.h"
|
#include "platform/dvxPlatform.h"
|
||||||
|
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
@ -221,61 +220,12 @@ void shellRegisterDesktopUpdate(void (*updateFn)(void)) {
|
||||||
// main
|
// main
|
||||||
// ============================================================
|
// ============================================================
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(void) {
|
||||||
(void)argc;
|
|
||||||
|
|
||||||
// Change to the directory containing the executable so that relative
|
|
||||||
// paths (CONFIG/, APPS/, etc.) resolve correctly regardless of where
|
|
||||||
// the user launched from.
|
|
||||||
char exeDir[260];
|
|
||||||
strncpy(exeDir, argv[0], sizeof(exeDir) - 1);
|
|
||||||
exeDir[sizeof(exeDir) - 1] = '\0';
|
|
||||||
|
|
||||||
char *sep = platformPathDirEnd(exeDir);
|
|
||||||
|
|
||||||
if (sep) {
|
|
||||||
*sep = '\0';
|
|
||||||
platformChdir(exeDir);
|
|
||||||
}
|
|
||||||
|
|
||||||
sLogFile = fopen("dvx.log", "w");
|
sLogFile = fopen("dvx.log", "w");
|
||||||
shellLog("DVX Shell starting...");
|
shellLog("DVX Shell starting...");
|
||||||
|
|
||||||
// Load preferences (missing file or keys silently use defaults)
|
|
||||||
prefsLoad("CONFIG/DVX.INI");
|
|
||||||
|
|
||||||
int32_t videoW = prefsGetInt("video", "width", 640);
|
|
||||||
int32_t videoH = prefsGetInt("video", "height", 480);
|
|
||||||
int32_t videoBpp = prefsGetInt("video", "bpp", 32);
|
|
||||||
shellLog("Preferences: video %ldx%ld %ldbpp", (long)videoW, (long)videoH, (long)videoBpp);
|
|
||||||
|
|
||||||
// Initialize GUI
|
// Initialize GUI
|
||||||
int32_t result = dvxInit(&sCtx, videoW, videoH, videoBpp);
|
int32_t result = dvxInit(&sCtx, 640, 480, 32);
|
||||||
|
|
||||||
if (result == 0) {
|
|
||||||
// Apply mouse preferences
|
|
||||||
const char *wheelStr = prefsGetString("mouse", "wheel", "normal");
|
|
||||||
int32_t wheelDir = (strcmp(wheelStr, "reversed") == 0) ? -1 : 1;
|
|
||||||
int32_t dblClick = prefsGetInt("mouse", "doubleclick", 500);
|
|
||||||
|
|
||||||
// Map acceleration name to double-speed threshold (mickeys/sec).
|
|
||||||
// "off" sets a very high threshold so acceleration never triggers.
|
|
||||||
const char *accelStr = prefsGetString("mouse", "acceleration", "medium");
|
|
||||||
int32_t accelVal = 0;
|
|
||||||
|
|
||||||
if (strcmp(accelStr, "off") == 0) {
|
|
||||||
accelVal = 10000;
|
|
||||||
} else if (strcmp(accelStr, "low") == 0) {
|
|
||||||
accelVal = 100;
|
|
||||||
} else if (strcmp(accelStr, "medium") == 0) {
|
|
||||||
accelVal = 64;
|
|
||||||
} else if (strcmp(accelStr, "high") == 0) {
|
|
||||||
accelVal = 32;
|
|
||||||
}
|
|
||||||
|
|
||||||
dvxSetMouseConfig(&sCtx, wheelDir, dblClick, accelVal);
|
|
||||||
shellLog("Preferences: mouse wheel=%s doubleclick=%ldms accel=%s", wheelStr, (long)dblClick, accelStr);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (result != 0) {
|
if (result != 0) {
|
||||||
shellLog("Failed to initialize DVX GUI (error %ld)", (long)result);
|
shellLog("Failed to initialize DVX GUI (error %ld)", (long)result);
|
||||||
|
|
@ -409,7 +359,6 @@ int main(int argc, char *argv[]) {
|
||||||
|
|
||||||
tsShutdown();
|
tsShutdown();
|
||||||
dvxShutdown(&sCtx);
|
dvxShutdown(&sCtx);
|
||||||
prefsFree();
|
|
||||||
|
|
||||||
shellLog("DVX Shell exited.");
|
shellLog("DVX Shell exited.");
|
||||||
|
|
||||||
|
|
|
||||||
BIN
releases/dvx-a1.zip
(Stored with Git LFS)
BIN
releases/dvx-a1.zip
(Stored with Git LFS)
Binary file not shown.
Loading…
Add table
Reference in a new issue