Much debugging. Starting to add actual client code!

This commit is contained in:
Scott Duensing 2021-11-11 20:19:25 -06:00
parent 7cf6a7112a
commit 30c8947936
34 changed files with 905 additions and 525 deletions

View file

@ -16,6 +16,9 @@
# along with this program. If not, see <https://www.gnu.org/licenses/>.
#
# NOTE: You'll occasionally find a file with a capital "C" extension.
# These are C files that we want ignored by the DOS compiler.
TEMPLATE = app
CONFIG -= qt
@ -47,14 +50,16 @@ INCLUDEPATH += \
HEADERS = \
$$LINUX_HEADERS \
src/settings.h \
src/system/color.h \
src/system/memory.h \
src/system/surface.h \
src/system/taglist.h \
src/test.h \
src/thirdparty/stb_ds.h \
src/thirdparty/stb_image.h \
src/thirdparty/memwatch/memwatch.h \
src/thirdparty/minicoro/minicoro.h \
src/system/memory.h \
src/system/keyboard.h \
src/system/task.h \
src/system/timer.h \
@ -80,14 +85,17 @@ HEADERS = \
src/gui/widget.h \
src/gui/window.h \
src/gui/image.h \
src/stddclmr.h
src/stddclmr.h \
src/welcome.h
SOURCES = \
$$LINUX_SOURCES \
src/system/memory.c \
src/thirdparty/memwatch/memwatch.c \
src/settings.c \
src/system/surface.c \
src/system/taglist.c \
src/thirdparty/memwatch/memwatch.c \
src/system/memory.c \
src/test.c \
src/system/array.c \
src/system/log.c \
src/system/timer.c \
@ -108,7 +116,8 @@ SOURCES = \
src/gui/button.c \
src/gui/checkbox.c \
src/gui/label.c \
src/main.c
src/main.c \
src/welcome.c
LIBS = \
-lSDL2 \

BIN
client/data/dconnect.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/ddialing.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/dinit.png (Stored with Git LFS) Normal file

Binary file not shown.

BIN
client/data/logo.png (Stored with Git LFS) Normal file

Binary file not shown.

View file

@ -34,11 +34,7 @@ void buttonClickHandlerSet(ButtonT *button, widgetCallback callback) {
static void buttonDel(WidgetT **widget) {
ButtonT *b = (ButtonT *)*widget;
arrfree(b->base.children);
if (b->title) free(b->title);
free(b);
b = NULL;
*widget = W(b);
}

View file

@ -34,11 +34,7 @@ void checkboxClickHandlerSet(CheckboxT *checkbox, widgetCallback callback) {
static void checkboxDel(WidgetT **widget) {
CheckboxT *c = (CheckboxT *)*widget;
arrfree(c->base.children);
if (c->title) free(c->title);
free(c);
c = NULL;
*widget = W(c);
}

View file

@ -22,26 +22,13 @@
#include "window.h"
static void desktopDel(WidgetT **widget);
static void desktopPaint(WidgetT *desktop, RectT pos);
static void desktopDel(WidgetT **widget) {
DesktopT *d = (DesktopT *)*widget;
arrfree(d->base.children);
surfaceDestroy(&d->base.surface);
free(d);
d = NULL;
*widget = W(d);
}
WidgetT *desktopInit(WidgetT *desktop) {
DesktopT *d = (DesktopT *)desktop;
d->base.magic = MAGIC_DESKTOP;
d->base.delMethod = desktopDel;
d->base.paintMethod = desktopPaint;
GUI_SET_FLAG(desktop, WIDGET_FLAG_OWNS_SURFACE);

View file

@ -28,11 +28,7 @@ static void framePaint(WidgetT *widget, RectT pos);
static void frameDel(WidgetT **widget) {
FrameT *f = (FrameT *)*widget;
arrfree(f->base.children);
if (f->title) free(f->title);
free(f);
f = NULL;
*widget = W(f);
}

View file

@ -39,10 +39,12 @@ uint16_t _guiDragOffsetY = 0;
WindowT *_guiActiveWindow = NULL;
static DesktopT *_guiDesktop = NULL;
static WidgetT *_guiLastWidgetLeft = NULL;
static uint8_t _guiLastWidgetLeftEvent = MOUSE_EVENT_NONE;
static WidgetT *_guiFocused = NULL;
static DesktopT *_guiDesktop = NULL;
static WidgetT *_guiLastWidgetLeft = NULL;
static uint8_t _guiLastWidgetLeftEvent = MOUSE_EVENT_NONE;
static WidgetT *_guiFocused = NULL;
static uint8_t _guiHasStopped = 0;
static WidgetT ***_guiDeleteList = NULL;
// Widget Magic Debug Info
@ -63,6 +65,8 @@ static char *_magicDebugNames[MAGIC_COUNT] = {
};
static void guiDeleteList(void);
static void guiDeleteListItem(WidgetT **widget);
static void guiPaintBoundsGet(WidgetT *widget, RectT *pos);
static void guiKeyboardChildrenProcess(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
static uint8_t guiMouseChildrenProcess(WidgetT *widget, MouseT *mouse);
@ -120,7 +124,7 @@ void guiAttach(WidgetT *parent, WidgetT *child) {
void guiComposite() {
WidgetT *widget = (WidgetT *)_guiDesktop;
size_t len = arrlenu(widget->children);
size_t len;
size_t x;
// Repaint anyone who needs it.
@ -133,9 +137,8 @@ void guiComposite() {
surfaceBlit(widget->surface, widget->pos.x, widget->pos.y);
}
//***TODO*** This is wrong. Should be recursive.
// Now render all surface-containing children to the VBE buffer.
len = arrlenu(widget->children);
if (len > 0) {
for (x=0; x<len; x++) {
if (GUI_GET_FLAG(widget->children[x], WIDGET_FLAG_OWNS_SURFACE)) {
@ -146,20 +149,113 @@ void guiComposite() {
}
void guiDebugAreaShow(WidgetT *widget) {
RectT r;
guiWidgetBoundsDrawableOnScreenGet(widget, &r);
logWrite("%s: %dx%d\n", _magicDebugNames[widget->magic], r.w, r.h);
}
void guiDebugWidgetTreeDump(WidgetT *widget, uint16_t depth) {
size_t len = arrlenu(widget->children);
size_t x;
char line[256];
for (x=0; x<depth*2; x++) line[x] = '-';
line[x] = 0;
logWrite("%s %s P:%dx%d-%dx%d M:%dx%d-%dx%d C:%dx%d-%dx%d F:%d\n",
line,
_magicDebugNames[widget->magic],
widget->pos.x, widget->pos.y, widget->pos.w, widget->pos.h,
widget->margin.x, widget->margin.y, widget->margin.w, widget->margin.h,
widget->clip.x, widget->clip.y, widget->clip.w, widget->clip.h,
widget->flags);
// Mark all children.
if (len > 0) {
for (x=0; x<len; x++) {
guiDebugWidgetTreeDump(widget->children[x], depth + 1);
}
}
}
void guiDelete(WidgetT **widget) {
WidgetT *w = *widget;
size_t len = arrlenu(w->children);
size_t x = 0;
// Since deleting happens in widget events, it's not safe to do it
// immediately. Instead, we make a list of what to delete and
// then process it before painting.
arrput(_guiDeleteList, widget);
}
static void guiDeleteList(void) {
WidgetT **w = NULL;
while (arrlen(_guiDeleteList) > 0) {
w = arrpop(_guiDeleteList);
guiDeleteListItem(w);
}
arrfree(_guiDeleteList);
_guiDeleteList = NULL;
}
static void guiDeleteListItem(WidgetT **widget) {
WidgetT *w = *widget;
size_t len = arrlenu(w->children);
size_t plen = arrlen(w->parent != NULL ? w->parent->children : 0);
size_t x = 0;
uint8_t nuke = 1;
static uint16_t depth = 0;
// Delete children.
if (len > 0) {
for (x=0; x<len; x++) {
guiDelete(&w->children[x]);
depth++;
guiDeleteListItem(&w->children[x]);
depth--;
}
}
// Remove us from parent children list.
if (depth == 0) {
if (plen > 0) {
for (x=0; x<plen; x++) {
if (w == w->parent->children[x]) {
arrdel(w->parent->children, x);
break;
}
}
// Was this the last child in the list?
if (plen == 1) {
// Erase the list.
arrfree(w->parent->children);
w->parent->children = NULL;
}
}
}
// If we were involved in a mouse event, get out of it.
if (w == _guiLastWidgetLeft) _guiLastWidgetLeft = NULL;
if (w == _guiFocused) _guiFocused = NULL;
// Delete us.
w->delMethod(&w);
//logWrite("Deleting %s %p\n", _magicDebugNames[w->magic], w);
if (w->delMethod != NULL) w->delMethod(&w);
arrfree(w->children);
if (w->surface != NULL) {
// Only free the surface if we own it. If it's our parent's, ignore.
if (w->parent != NULL) {
if (w->surface == w->parent->surface) nuke = 0;
}
if (nuke) surfaceDestroy(&w->surface);
}
free(w);
w = NULL;
*widget = w;
// Make sure we're not drawing into oblivion.
surfaceSet(NULL);
@ -195,6 +291,11 @@ void guiFocusSet(WidgetT *widget) {
}
uint8_t guiHasStopped(void) {
return _guiHasStopped;
}
static void guiKeyboardChildrenProcess(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) {
size_t len;
size_t x;
@ -246,21 +347,13 @@ static uint8_t guiMouseChildrenProcess(WidgetT *widget, MouseT *mouse) {
uint8_t event = MOUSE_EVENT_NONE;
static WidgetT *focusDown = NULL;
// Search children backwards for active widget before checking this widget.
len = arrlenu(widget->children);
for (x=len-1; x>=0; --x) {
if (guiMouseChildrenProcess(widget->children[x], mouse)) {
return 1;
}
}
// Get widget and screen coordinates of pointer.
guiWidgetPositionOnScreenGet(widget, &r);
sx = r.x;
sy = r.y;
guiMousePositionOnWidgetGet(widget, mouse, &mx, &my);
//logWrite("Mouse %dx%d Widget %s %dx%d\n", mouse->x, mouse->y, MagicDebugNames[widget->magic], sx, sy);
//logWrite("Mouse %dx%d Widget %s %dx%d Screen %dx%d\n", mouse->x, mouse->y, _magicDebugNames[widget->magic], mx, my, sx, sy);
// Serious hack to make window dragging work better.
// This is because it's possible to move the mouse faster than METRIC_WINDOW_TITLE_GRAB_HEIGHT pixels
@ -270,6 +363,14 @@ static uint8_t guiMouseChildrenProcess(WidgetT *widget, MouseT *mouse) {
return 1;
}
// Search children backwards for active widget before checking this widget.
len = arrlenu(widget->children);
for (x=len-1; x>=0; --x) {
if (guiMouseChildrenProcess(widget->children[x], mouse)) {
return 1;
}
}
// Is the mouse inside this widget?
if (mouse->x >= sx && mouse->y >= sy && mouse->x < sx + widget->pos.w && mouse->y < sy + widget->pos.h) {
@ -277,7 +378,9 @@ static uint8_t guiMouseChildrenProcess(WidgetT *widget, MouseT *mouse) {
if (_guiLastWidgetLeft != widget) {
// Tell previous widget we're moving out.
if (_guiLastWidgetLeft->mouseEventMethod) _guiLastWidgetLeft->mouseEventMethod(_guiLastWidgetLeft, mouse, mx, my, MOUSE_EVENT_OUT);
if (_guiLastWidgetLeft) {
if (_guiLastWidgetLeft->mouseEventMethod) _guiLastWidgetLeft->mouseEventMethod(_guiLastWidgetLeft, mouse, mx, my, MOUSE_EVENT_OUT);
}
// Tell new widget we've moved in.
event = MOUSE_EVENT_IN;
@ -329,10 +432,13 @@ void guiMouseProcess(MouseT *mouse) {
void guiPaint(WidgetT *widget) {
size_t len = arrlenu(widget->children);
size_t len;
size_t x;
RectT pos;
// Process any pending widget deletions.
guiDeleteList();
// Paint us. Widget handles dirty flag so they can animate if needed.
if (widget->paintMethod) {
surfaceSet(widget->surface);
@ -341,6 +447,7 @@ void guiPaint(WidgetT *widget) {
}
// Paint all children.
len = arrlenu(widget->children);
if (len > 0) {
for (x=0; x<len; x++) {
guiPaint(widget->children[x]);
@ -368,6 +475,19 @@ WidgetT *guiRootGet(void) {
}
void guiShutdown(void) {
// Unload fonts.
fontUnload(&_guiFont16);
fontUnload(&_guiFont14);
fontUnload(&_guiFont8);
_guiFont = NULL;
// Delete all widgets in GUI tree.
guiDelete((WidgetT **)&_guiDesktop);
guiDeleteList();
}
DesktopT *guiStartup(void) {
_guiMetric[METRIC_BUTTON_BEZEL_SIZE] = 2;
@ -457,15 +577,8 @@ DesktopT *guiStartup(void) {
}
void guiShutdown(void) {
// Unload fonts.
fontUnload(&_guiFont16);
fontUnload(&_guiFont14);
fontUnload(&_guiFont8);
_guiFont = NULL;
// Delete all widgets in GUI tree.
guiDelete((WidgetT **)&_guiDesktop);
void guiStop(void) {
_guiHasStopped = 1;
}
@ -525,28 +638,3 @@ void guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos) {
}
}
void guiWidgetTreeDump(WidgetT *widget, uint16_t depth) {
size_t len = arrlenu(widget->children);
size_t x;
char line[256];
for (x=0; x<depth*2; x++) line[x] = '-';
line[x] = 0;
logWrite("%s %s P:%dx%d-%dx%d M:%dx%d-%dx%d C:%dx%d-%dx%d F:%d\n",
line,
_magicDebugNames[widget->magic],
widget->pos.x, widget->pos.y, widget->pos.w, widget->pos.h,
widget->margin.x, widget->margin.y, widget->margin.w, widget->margin.h,
widget->clip.x, widget->clip.y, widget->clip.w, widget->clip.h,
widget->flags);
// Mark all children.
if (len > 0) {
for (x=0; x<len; x++) {
guiWidgetTreeDump(widget->children[x], depth + 1);
}
}
}

View file

@ -36,6 +36,7 @@
#define GUI_CLEAR_FLAG(w,f) ((w)->flags &= (~(1 << (f))))
#define W(w) ((WidgetT *)w)
#define D(w) ((WidgetT **)&w)
// Widget Magics
@ -161,22 +162,25 @@ extern WindowT *_guiActiveWindow;
void guiAttach(WidgetT *parent, WidgetT *child);
void guiComposite(void);
void guiDebugAreaShow(WidgetT *widget);
void guiDebugWidgetTreeDump(WidgetT *widget, uint16_t depth);
void guiDelete(WidgetT **widget);
WidgetT *guiFocusGet(void);
void guiFocusSet(WidgetT *widget);
uint8_t guiHasStopped(void);
void guiKeyboardProcess(uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y);
void guiMouseProcess(MouseT *mouse);
void guiPaint(WidgetT *widget);
WidgetT *guiRootGet(void);
DesktopT *guiStartup(void);
void guiShutdown(void);
DesktopT *guiStartup(void);
void guiStop(void);
void *guiUserDataGet(WidgetT *widget);
void guiUserDataSet(WidgetT *widget, void *userData);
void guiWidgetAndChildrenDirtySet(WidgetT *widget);
void guiWidgetBoundsDrawableOnScreenGet(WidgetT *widget, RectT *bounds);
void guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos);
void guiWidgetTreeDump(WidgetT *widget, uint16_t depth);
#endif // GUI_H

View file

@ -52,11 +52,7 @@ void labelColorForegroundSet(LabelT *label, ColorT color) {
static void labelDel(WidgetT **widget) {
LabelT *l = (LabelT *)*widget;
arrfree(l->base.children);
if (l->title) free(l->title);
free(l);
l = NULL;
*widget = W(l);
}

View file

@ -52,12 +52,6 @@ static void listboxDel(WidgetT **widget) {
}
}
arrfree(l->values);
arrfree(l->base.children);
if (l->title) free(l->title);
free(l);
l = NULL;
*widget = W(l);
}

View file

@ -34,12 +34,8 @@ void pictureClickHandlerSet(PictureT *picture, widgetCallback callback) {
static void pictureDel(WidgetT **widget) {
PictureT *p = (PictureT *)*widget;
arrfree(p->base.children);
if (p->image) imageUnload(&p->image);
if (p->filename) free(p->filename);
free(p);
p = NULL;
*widget = W(p);
}

View file

@ -36,11 +36,7 @@ void radioClickHandlerSet(RadioT *radio, widgetCallback callback) {
static void radioDel(WidgetT **widget) {
RadioT *r = (RadioT *)*widget;
arrfree(r->base.children);
if (r->title) free(r->title);
free(r);
r = NULL;
*widget = W(r);
}

View file

@ -502,11 +502,6 @@ static void terminalDel(WidgetT **widget) {
free(t->cells[x]);
}
free(t->cells);
arrfree(t->base.children);
free(t);
t = NULL;
*widget = W(t);
}

View file

@ -32,12 +32,8 @@ static void textboxPaint(WidgetT *widget, RectT pos);
static void textboxDel(WidgetT **widget) {
TextboxT *t = (TextboxT *)*widget;
arrfree(t->base.children);
if (t->title) free(t->title);
if (t->value) free(t->value);
free(t);
t = NULL;
*widget = W(t);
}

View file

@ -47,11 +47,7 @@ static void updownVisibleSet(UpdownT *updown);
static void updownDel(WidgetT **widget) {
UpdownT *u = (UpdownT *)*widget;
arrfree(u->base.children);
if (u->title) free(u->title);
free(u);
u = NULL;
*widget = W(u);
}

View file

@ -22,19 +22,6 @@
#include "window.h"
static void widgetDel(WidgetT **widget);
static void widgetDel(WidgetT **widget) {
WidgetT *w = (WidgetT *)*widget;
arrfree(w->children);
free(w);
w = NULL;
*widget = w;
}
uint16_t widgetHeightGet(WidgetT *widget) {
return widget->pos.h;
}
@ -59,7 +46,7 @@ WidgetT *widgetInit(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint
widget->children = NULL;
widget->parent = NULL;
widget->window = NULL;
widget->delMethod = widgetDel;
widget->delMethod = NULL;
widget->focusMethod = NULL;
widget->keyboardEventMethod = NULL;
widget->paintMethod = NULL;

View file

@ -79,12 +79,7 @@ static void windowAllDeactivate(WidgetT *widget) {
static void windowDel(WidgetT **widget) {
WindowT *w = (WindowT *)*widget;
surfaceDestroy(&w->base.surface);
arrfree(w->base.children);
if (w->title) free(w->title);
free(w);
w = NULL;
*widget = W(w);
}

View file

@ -37,6 +37,7 @@ static MouseT _mouse;
static SDL_Window *_window = NULL;
static SDL_Renderer *_renderer = NULL;
static SDL_Surface *_surface = NULL;
static SDL_Texture *_texture = NULL;
static uint16_t _width = 0;
static uint16_t _height = 0;
static uint8_t _windowScale = 1;
@ -253,40 +254,28 @@ uint16_t vbeDisplayWidthGet(void) {
ColorT vbeColorMake(uint8_t red, uint8_t green, uint8_t blue) {
// Pixels are 8:8:8:8 RGBA - SDL_PIXELFORMAT_RGBA8888
return
(red << 24) |
(green << 16) |
(blue << 8);
(blue << 8) |
255;
}
void vbePresent(void) {
uint16_t x;
uint16_t y;
SurfaceT *s = surfaceOffScreenGet();
uint32_t p;
uint8_t r;
uint8_t g;
uint8_t b;
SDL_SetRenderTarget(_renderer, NULL);
//***TODO*** This is stupid inefficient.
for (y=0; y<s->height; y++) {
for (x=0; x<s->width; x++) {
p = s->buffer.bits32[y * s->width + x];
r = (p & 0xFF000000) >> 24;
g = (p & 0x00FF0000) >> 16;
b = (p & 0x0000FF00) >> 8;
SDL_SetRenderDrawColor(_renderer, r, g, b, 255);
SDL_RenderDrawPoint(_renderer, x, y);
}
}
void *pixels;
int pitch;
SurfaceT *s = surfaceOffScreenGet();
SDL_LockTexture(_texture, NULL, &pixels, &pitch);
memcpy(pixels, s->buffer.bits8, s->bytes);
SDL_UnlockTexture(_texture);
SDL_RenderCopy(_renderer, _texture, NULL, NULL);
SDL_RenderPresent(_renderer);
// Throttle this to some sane frame rate.
//SDL_Delay(32);
SDL_Delay(32);
}
@ -297,6 +286,11 @@ int16_t vbeInfoShow(void) {
int16_t vbeShutdown(void) {
if (_texture) {
SDL_DestroyTexture(_texture);
_texture = NULL;
}
if (_renderer) {
SDL_DestroyRenderer(_renderer);
_renderer = NULL;
@ -327,6 +321,7 @@ uint8_t vbeStartup(uint16_t xRes, uint16_t yRes, uint8_t bpp) {
_window = SDL_CreateWindow("GUI Test", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, xRes, yRes, SDL_WINDOW_ALLOW_HIGHDPI);
_surface = SDL_GetWindowSurface(_window);
_renderer = SDL_CreateRenderer(_window, -1, SDL_RENDERER_ACCELERATED);
_texture = SDL_CreateTexture(_renderer, SDL_PIXELFORMAT_RGBA8888, SDL_TEXTUREACCESS_STREAMING, xRes, yRes);
SDL_RenderSetLogicalSize(_renderer, xRes, yRes);
SDL_SetWindowSize(_window, xRes * _windowScale, yRes * _windowScale);

View file

@ -18,6 +18,9 @@
*/
//#define TESTING
/*
* To Do:
*
@ -29,7 +32,6 @@
* - Use LabelT in all widgets that have a label
* - Find a light grey to replace white widget data areas
* - No thumb in listbox scrollbar
* - Window dragging is being screwball
*
* - Random crash on exit - looks memwatch / task related - hasn't happened on DOS yet
*/
@ -45,48 +47,25 @@
#include "image.h"
#include "font.h"
#include "timer.h"
#include "gui.h"
#include "widget.h"
#include "desktop.h"
#include "window.h"
#include "button.h"
#include "label.h"
#include "checkbox.h"
#include "radio.h"
#include "picture.h"
#include "frame.h"
#include "textbox.h"
#include "updown.h"
#include "listbox.h"
#include "terminal.h"
#include "taglist.h"
#include "welcome.h"
#ifdef TESTING
#include "test.h"
#endif
static TerminalT *t1 = NULL;
static uint8_t lastKey = 0;
static void taskGuiEventLoop(void *data);
static void buttonClick(WidgetT *widget);
static void mainLoop(void *data);
//static void test(void *data);
static void testTagList(void *data);
static void testTerminal(void *data);
static void widgetDebugDraw(WidgetT *widget, uint8_t debugToggle);
static void buttonClick(WidgetT *widget) {
logWrite("'%s' was clicked.\n", ((ButtonT *)widget)->title);
}
static void mainLoop(void *data) {
static void taskGuiEventLoop(void *data) {
MouseT *mouse = NULL;
ImageT *pointer = NULL;
ColorT alpha;
int8_t key = 0;
#ifdef TESTING
int8_t debugState = 0;
#endif
(void)data;
@ -97,17 +76,17 @@ static void mainLoop(void *data) {
timerUpdate();
mouse = mouseRead();
if (keyHit()) {
key = keyASCIIGet();
lastKey = key; //***DEBUG***
#ifdef TESTING
lastKey = keyASCIIGet(); //***DEBUG***
#endif
guiKeyboardProcess(keyASCIIGet(), keyExtendedGet(), keyScanCodeGet(), keyShiftGet(), keyControlGet(), keyAltGet());
//logWrite("Key '%d' Extended '%d' Scancode '%d' Shift '%d' Control '%d' Alt '%d'\n", key, keyExtended(), keyScanCode(), keyShift(), keyControl(), keyAlt());
} else {
key = 0;
//logWrite("Key '%d' Extended '%d' Scancode '%d' Shift '%d' Control '%d' Alt '%d'\n", keyASCIIGet(), keyExtended(), keyScanCode(), keyShift(), keyControl(), keyAlt());
}
guiMouseProcess(mouse);
guiComposite();
imageRenderWithAlpha(pointer, mouse->x, mouse->y, alpha);
#ifdef TESTING
if (key == '=') guiWidgetTreeDump(guiRootGet(), 0);
if (key == '+') {
debugState++;
@ -115,308 +94,30 @@ static void mainLoop(void *data) {
}
if (debugState > 0) widgetDebugDraw(guiRootGet(), debugState - 1);
//if (timerHalfSecondOn) guiDrawRectangle(0, 0, vbeSurfaceWidthGet() - 1, vbeSurfaceHeightGet() - 1, vbeMakeColor(255, 255, 255));
#endif
vbeVBlankWait();
vbePresent();
taskYield();
#ifdef TESTING
} while (key != 27); // Exit on ESC.
#else
} while (!guiHasStopped());
#endif
imageUnload(&pointer);
}
/*
static void test(void *data) {
DesktopT *desktop = (DesktopT *)guiRootGet();
WindowT *w1 = NULL;
WindowT *w2 = NULL;
WindowT *w3 = NULL;
WindowT *w4 = NULL;
ButtonT *b1 = NULL;
LabelT *l1 = NULL;
CheckboxT *c1 = NULL;
RadioT *r1a = NULL;
RadioT *r2a = NULL;
RadioT *r3a = NULL;
RadioT *r1b = NULL;
RadioT *r2b = NULL;
RadioT *r3b = NULL;
PictureT *p1 = NULL;
FrameT *f1 = NULL;
TextboxT *tb1 = NULL;
TextboxT *tb2 = NULL;
UpdownT *u1 = NULL;
ListboxT *lb1 = NULL;
(void)data;
// Windows
w1 = windowNew(300, 25, 300, 200, "Window 1");
guiAttach(W(desktop), W(w1));
w2 = windowNew(150, 150, 300, 200, "Window 2");
guiAttach(W(desktop), W(w2));
w3 = windowNew(300, 300, 300, 200, "Window 3");
guiAttach(W(desktop), W(w3));
w4 = windowNew(10, 10, 7 + 8 + (80 * 8), 26 + 8 + (24 * 14), "Terminal");
guiAttach(W(desktop), W(w4));
// Window 1
p1 = pictureNew(0, 0, "kanga.png");
guiAttach(W(w1), W(p1));
lb1 = listboxNew(155, 10, 120, 140, "List Box");
listboxItemAdd(lb1, "One");
listboxItemAdd(lb1, "Two");
listboxItemAdd(lb1, "Three");
listboxItemAdd(lb1, "Four");
listboxItemAdd(lb1, "Five");
listboxItemAdd(lb1, "Six");
listboxItemAdd(lb1, "Seven");
listboxItemAdd(lb1, "Eight");
listboxItemAdd(lb1, "Nine");
listboxItemAdd(lb1, "Ten");
listboxStepSet(lb1, 3);
guiAttach(W(w1), W(lb1));
// Window 2
r1a = radioNew(10, 10, "Radio 1a", 1);
guiAttach(W(w2), W(r1a));
r2a = radioNew(20 + widgetWidthGet(W(r1a)), 10, "Radio 2a", 1);
guiAttach(W(w2), W(r2a));
r3a = radioNew(30 + widgetWidthGet(W(r1a)) + widgetWidthGet(W(r2a)), 10, "Radio 3a", 1);
guiAttach(W(w2), W(r3a));
r1b = radioNew(10, 35, "Radio 1b", 2);
guiAttach(W(w2), W(r1b));
r2b = radioNew(20 + widgetWidthGet(W(r1b)), 35, "Radio 2b", 2);
guiAttach(W(w2), W(r2b));
r3b = radioNew(30 + widgetWidthGet(W(r1b)) + widgetWidthGet(W(r2b)), 35, "Radio 3b", 2);
guiAttach(W(w2), W(r3b));
radioSelectedSet(r1a);
radioSelectedSet(r2b);
tb1 = textboxNew(10, 60, 265, "Test Textbox");
textboxValueSet(tb1, "Really long text string to edit!");
guiAttach(W(w2), W(tb1));
tb2 = textboxNew(10, 85, 265, "Test Textbox");
textboxValueSet(tb2, "Short string.");
guiAttach(W(w2), W(tb2));
u1 = updownNew(10, 110, 0, 1024, 5, "UpDown");
guiAttach(W(w2), W(u1));
// Window 3
f1 = frameNew(10, 5, 175, 125, "Test Frame");
guiAttach(W(w3), W(f1));
b1 = buttonNew(0, 0, "Test Button", buttonClick);
guiAttach(W(f1), W(b1));
l1 = labelNew(10, 40, "Test Label");
guiAttach(W(f1), W(l1));
c1 = checkboxNew(10, 65, "Test Checkbox");
guiAttach(W(f1), W(c1));
// Window 4 - Terminal
t1 = terminalNew(0, 0, 80, 24);
guiAttach(W(w4), W(t1));
taskCreate(testTerminal, "terminalTest");
}
*/
static void testTagList(void *data) {
WindowT *w1 = NULL;
WindowT *w2 = NULL;
WindowT *w3 = NULL;
WindowT *w4 = NULL;
ButtonT *b1 = NULL;
LabelT *l1 = NULL;
CheckboxT *c1 = NULL;
RadioT *r1a = NULL;
RadioT *r2a = NULL;
RadioT *r3a = NULL;
RadioT *r1b = NULL;
RadioT *r2b = NULL;
RadioT *r3b = NULL;
PictureT *p1 = NULL;
FrameT *f1 = NULL;
TextboxT *tb1 = NULL;
TextboxT *tb2 = NULL;
UpdownT *u1 = NULL;
ListboxT *lb1 = NULL;
(void)data;
TagItemT ui[] = {
T_START,
T_WINDOW, O(w1),
T_TITLE, P("Window 1"),
T_X, 300, T_Y, 25, T_WIDTH, 300, T_HEIGHT, 200,
T_PICTURE, O(p1),
T_X, 0, T_Y, 0,
T_FILENAME, P("kanga.png"),
T_PICTURE, T_DONE,
T_LISTBOX, O(lb1),
T_TITLE, P("Listbox"),
T_X, 155, T_Y, 10, T_WIDTH, 120, T_HEIGHT, 140,
T_ITEM, P("One"),
T_ITEM, P("Two"),
T_ITEM, P("Three"),
T_ITEM, P("Four"),
T_ITEM, P("Five"),
T_ITEM, P("Six"),
T_ITEM, P("Seven"),
T_ITEM, P("Eight"),
T_ITEM, P("Nine"),
T_ITEM, P("Ten"),
T_STEP, 3,
T_LISTBOX, T_DONE,
T_WINDOW, T_DONE,
T_WINDOW, O(w2),
T_TITLE, P("Window 2"),
T_X, 150, T_Y, 150, T_WIDTH, 300, T_HEIGHT, 200,
T_RADIOBUTTON, O(r1a),
T_TITLE, P("Radio 1a"),
T_X, 10, T_Y, 10,
T_GROUP, 1,
T_SELECTED, 1,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r2a),
T_TITLE, P("Radio 2a"),
T_X, 20 + 80, T_Y, 10,
T_GROUP, 1,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r3a),
T_TITLE, P("Radio 3a"),
T_X, 30 + 80 * 2, T_Y, 10,
T_GROUP, 1,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r1b),
T_TITLE, P("Radio 1b"),
T_X, 10, T_Y, 35,
T_GROUP, 2,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r2b),
T_TITLE, P("Radio 2b"),
T_X, 20 + 80, T_Y, 35,
T_GROUP, 2,
T_SELECTED, 1,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r3b),
T_TITLE, P("Radio 3b"),
T_X, 30 + 80 * 2, T_Y, 35,
T_GROUP, 2,
T_RADIOBUTTON, T_DONE,
T_TEXTBOX, O(tb1),
T_TITLE, P("Test Textbox"),
T_X, 10, T_Y, 60, T_WIDTH, 265,
T_VALUE, P("Really long text string to edit!"),
T_TEXTBOX, T_DONE,
T_TEXTBOX, O(tb2),
T_TITLE, P("Test Textbox"),
T_X, 10, T_Y, 85, T_WIDTH, 265,
T_VALUE, P("Short String."),
T_TEXTBOX, T_DONE,
T_UPDOWN, O(u1),
T_TITLE, P("UpDown"),
T_X, 10, T_Y, 120,
T_MINIMUM, 0, T_MAXIMUM, 1024, T_STEP, 5,
T_UPDOWN, T_DONE,
T_WINDOW, T_DONE,
T_WINDOW, O(w3),
T_TITLE, P("Window 3"),
T_X, 300, T_Y, 300, T_WIDTH, 300, T_HEIGHT, 200,
T_FRAME, O(f1),
T_TITLE, P("Test Frame"),
T_X, 10, T_Y, 5, T_WIDTH, 175, T_HEIGHT, 125,
T_BUTTON, O(b1),
T_TITLE, P("Test Button"),
T_X, 0, T_Y, 0,
T_CLICK, P(buttonClick),
T_BUTTON, T_DONE,
T_LABEL, O(l1),
T_TITLE, P("Test Label"),
T_X, 10, T_Y, 40,
T_LABEL, T_DONE,
T_CHECKBOX, O(c1),
T_TITLE, P("Test Checkbox"),
T_X, 10, T_Y, 65,
T_CHECKBOX, T_DONE,
T_FRAME, T_DONE,
T_WINDOW, T_DONE,
T_WINDOW, O(w4),
T_TITLE, P("Terminal"),
T_X, 10, T_Y, 10, T_WIDTH, 7 + 8 + (80 * 8), T_HEIGHT, 26 + 8 + (24 * 14),
T_TERMINAL, O(t1),
T_X, 0, T_Y, 0, T_WIDTH, 80, T_HEIGHT, 24,
T_TERMINAL, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(ui);
taskCreate(testTerminal, "terminalTest");
}
static void testTerminal(void *data) {
FILE *in = NULL;
char *buffer = NULL;
uint16_t length = 0;
(void)data;
// Load ANSI file for terminal test.
in = fopen("kanga.ans", "rt");
fseek(in, 0, SEEK_END);
length = ftell(in);
fseek(in, 0, SEEK_SET);
buffer = (char *)malloc(length + 1);
fread(buffer, 1, length, in);
fclose(in);
buffer[length] = 0;
terminalStringPrint(t1, buffer);
free(buffer);
}
static void widgetDebugDraw(WidgetT *widget, uint8_t debugToggle) {
size_t len = arrlenu(widget->children);
size_t i;
RectT r;
if (debugToggle) {
// Clipping region (blue)
guiWidgetBoundsDrawableOnScreenGet(widget, &r);
surfaceRectangleDraw(r.x, r.y, r.x + r.w, r.y + r.h, vbeColorMake(0, 0, 255));
} else {
// Widget border (red)
guiWidgetPositionOnScreenGet(widget, &r);
surfaceRectangleDraw(r.x, r.y, r.x + widget->pos.w, r.y + widget->pos.h, vbeColorMake(255, 0, 0));
}
if (len > 0) {
for (i=0; i<len; i++) {
widgetDebugDraw(widget->children[i], debugToggle);
}
}
}
int main(int argc, char *argv[]) {
uint16_t xResolution = 0;
uint16_t yResolution = 0;
uint16_t colorDepth = 0;
char logName[32] = { "log.log" };
char *c = NULL;
int16_t x = strlen(argv[0]);
memoryStartup();
memoryStartup(argv[0]);
logOpenByHandle(memoryLogHandleGet());
// 0 1 2 3 4 5 6 7 8
// 12345678901234567890123456789012345678901234567890123456789012345678901234567890
@ -424,21 +125,6 @@ int main(int argc, char *argv[]) {
printf("Copyright (C) 2020-2021 Scott Duensing scott@kangaroopunch.com\n\n");
fflush(stdout);
// Find last portion of filename.
while (x > 0) {
if (argv[0][x] == '/' || argv[0][x] == '\\') break;
x--;
}
if (strlen(argv[0]) - x < 32) {
// Replace any extension with ".log"
strncpy(logName, &argv[0][x + 1], 31);
c = strstr(logName, ".");
if (c) *c = 0;
strncat(logName, ".log", 31);
}
logOpen(logName, 0);
// Command line needs to have the desired resolution and color depth on it.
if (argc != 4) {
vbeInfoShow();
@ -463,8 +149,13 @@ int main(int argc, char *argv[]) {
guiStartup();
taskStartup();
taskCreate(testTagList, "testTagList");
taskCreate(mainLoop, "mainLoop");
#ifdef TESTING
taskCreate(taskTestTagList, NULL);
#else
taskCreate(taskWelcome, NULL);
#endif
taskCreate(taskGuiEventLoop, NULL);
taskRun();
taskShutdown();
@ -475,7 +166,6 @@ int main(int argc, char *argv[]) {
vbeShutdown();
logClose();
memoryShutdown();
return 0;

69
client/src/settings.c Normal file
View file

@ -0,0 +1,69 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "settings.h"
#include "welcome.h"
#include "taglist.h"
#include "task.h"
#include "window.h"
#include "button.h"
#include "frame.h"
#include "radio.h"
static WindowT *winSettings;
static FrameT *frmComPorts;
static ButtonT *btnOkay;
static void btnOkayClick(WidgetT *widget);
static void btnOkayClick(WidgetT *widget) {
(void)widget;
taskCreate(taskWelcome, NULL);
guiDelete(D(winSettings));
}
void taskSettings(void *data) {
(void)data;
TagItemT ui[] = {
T_START,
T_WINDOW, O(winSettings),
T_TITLE, P("Settings"),
T_WIDTH, 200, T_HEIGHT, 200,
T_BUTTON, O(btnOkay),
T_TITLE, P("Okay"),
T_CLICK, P(btnOkayClick),
T_BUTTON, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(ui);
guiDebugAreaShow(W(winSettings));
guiDebugAreaShow(W(btnOkay));
}

31
client/src/settings.h Normal file
View file

@ -0,0 +1,31 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef SETTINGS_H
#define SETTINGS_H
#include "os.h"
void taskSettings(void *data);
#endif // SETTINGS_H

View file

@ -21,19 +21,29 @@
#include "log.h"
FILE *_log = NULL;
static FILE *_log = NULL;
static uint8_t _ourHandle = 0;
uint8_t logOpen(char *filename, uint8_t append) {
_log = fopen(filename, append ? "a" : "w");
if (_log) return 1;
if (_log) {
return 1;
_ourHandle = 1;
}
return 0;
}
void logOpenByHandle(FILE *handle) {
_log = handle;
}
void logClose(void) {
if (_log) {
if (_log && _ourHandle) {
fclose(_log);
_ourHandle = 0;
}
}
@ -44,8 +54,8 @@ void logWrite(char *format, ...) {
va_start(args, format);
#ifdef __linux__
// Also output to stdout on Linux.
va_list args2;
va_copy(args2, args);
vfprintf(stdout, format, args2);
fflush(stdout);

View file

@ -26,6 +26,7 @@
uint8_t logOpen(char *filename, uint8_t append);
void logOpenByHandle(FILE *handle);
void logClose(void);
void logWrite(char *format, ...);

View file

@ -21,20 +21,60 @@
#include "memory.h"
#ifdef MEMWATCH_STDIO
FILE *_memoryLog = NULL;
#ifdef MEMORY_CHECK_ENABLED
void mwLogW(FILE *p);
#endif
FILE *memoryLogHandleGet(void) {
return _memoryLog;
}
#ifdef MEMORY_CHECK_ENABLED
void memoryOutput(int c) {
logWrite("%c", c);
fputc(c, _memoryLog);
fflush(_memoryLog);
fputc(c, stdout);
fflush(stdout);
}
#endif
void memoryShutdown(void) {
// Nada.
}
void memoryStartup(void) {
#ifdef MEMWATCH_STDIO
mwSetOutFunc(memoryOutput);
#ifdef MEMORY_CHECK_ENABLED
mwTerm();
#endif
}
void memoryStartup(char *appName) {
char logName[32] = { "log.log" };
char *c = NULL;
int16_t x = strlen(appName);
// Find last portion of filename.
while (x > 0) {
if (appName[x] == '/' || appName[x] == '\\') break;
x--;
}
if (strlen(appName) - x < 32) {
// Replace any extension with ".log"
strncpy(logName, &appName[x + 1], 31);
c = strstr(logName, ".");
if (c) *c = 0;
strncat(logName, ".log", 31);
}
_memoryLog = fopen(logName, "w");
#ifdef MEMORY_CHECK_ENABLED
mwLogW(_memoryLog);
mwSetOutFunc(memoryOutput);
mwInit();
#endif
}

View file

@ -24,16 +24,15 @@
#include "os.h"
#ifdef MEMORY_CHECK_ENABLED
#define MEMWATCH
#define MEMWATCH_STDIO
#include "memwatch/memwatch.h"
#endif
#include "memwatch/memwatch.h"
void memoryShutdown(void);
void memoryStartup(void);
FILE *memoryLogHandleGet(void);
void memoryShutdown(void);
void memoryStartup(char *appName);
#endif // MEMORY_H

View file

@ -247,6 +247,12 @@ static void tagListWidgetAttributeHandle(void) {
parent = *w->parent;
}
// Auto-center windows if position not specified.
if (pos.x == 0 && pos.y == 0 && w->type == T_WINDOW) {
pos.x = vbeDisplayWidthGet() / 2 - pos.w / 2;
pos.y = vbeDisplayHeightGet() / 2 - pos.h / 2;
}
// Create the widget.
switch (w->type) {
@ -316,7 +322,7 @@ static void tagListWidgetAttributeHandle(void) {
break;
}
guiUserDataSet(widget, userdata);
if (userdata != NULL) guiUserDataSet(widget, userdata);
// Store everything we did.
*w->widget = widget;

336
client/src/test.c Normal file
View file

@ -0,0 +1,336 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "test.h"
#include "task.h"
#include "gui.h"
#include "widget.h"
#include "desktop.h"
#include "window.h"
#include "button.h"
#include "label.h"
#include "checkbox.h"
#include "radio.h"
#include "picture.h"
#include "frame.h"
#include "textbox.h"
#include "updown.h"
#include "listbox.h"
#include "terminal.h"
#include "taglist.h"
uint8_t lastKey = 0;
static TerminalT *t1 = NULL;
static void buttonClick(WidgetT *widget);
//static void test(void *data);
static void testTerminal(void *data);
static void buttonClick(WidgetT *widget) {
logWrite("'%s' was clicked.\n", ((ButtonT *)widget)->title);
}
/*
static void test(void *data) {
DesktopT *desktop = (DesktopT *)guiRootGet();
WindowT *w1 = NULL;
WindowT *w2 = NULL;
WindowT *w3 = NULL;
WindowT *w4 = NULL;
ButtonT *b1 = NULL;
LabelT *l1 = NULL;
CheckboxT *c1 = NULL;
RadioT *r1a = NULL;
RadioT *r2a = NULL;
RadioT *r3a = NULL;
RadioT *r1b = NULL;
RadioT *r2b = NULL;
RadioT *r3b = NULL;
PictureT *p1 = NULL;
FrameT *f1 = NULL;
TextboxT *tb1 = NULL;
TextboxT *tb2 = NULL;
UpdownT *u1 = NULL;
ListboxT *lb1 = NULL;
(void)data;
// Windows
w1 = windowNew(300, 25, 300, 200, "Window 1");
guiAttach(W(desktop), W(w1));
w2 = windowNew(150, 150, 300, 200, "Window 2");
guiAttach(W(desktop), W(w2));
w3 = windowNew(300, 300, 300, 200, "Window 3");
guiAttach(W(desktop), W(w3));
w4 = windowNew(10, 10, 7 + 8 + (80 * 8), 26 + 8 + (24 * 14), "Terminal");
guiAttach(W(desktop), W(w4));
// Window 1
p1 = pictureNew(0, 0, "kanga.png");
guiAttach(W(w1), W(p1));
lb1 = listboxNew(155, 10, 120, 140, "List Box");
listboxItemAdd(lb1, "One");
listboxItemAdd(lb1, "Two");
listboxItemAdd(lb1, "Three");
listboxItemAdd(lb1, "Four");
listboxItemAdd(lb1, "Five");
listboxItemAdd(lb1, "Six");
listboxItemAdd(lb1, "Seven");
listboxItemAdd(lb1, "Eight");
listboxItemAdd(lb1, "Nine");
listboxItemAdd(lb1, "Ten");
listboxStepSet(lb1, 3);
guiAttach(W(w1), W(lb1));
// Window 2
r1a = radioNew(10, 10, "Radio 1a", 1);
guiAttach(W(w2), W(r1a));
r2a = radioNew(20 + widgetWidthGet(W(r1a)), 10, "Radio 2a", 1);
guiAttach(W(w2), W(r2a));
r3a = radioNew(30 + widgetWidthGet(W(r1a)) + widgetWidthGet(W(r2a)), 10, "Radio 3a", 1);
guiAttach(W(w2), W(r3a));
r1b = radioNew(10, 35, "Radio 1b", 2);
guiAttach(W(w2), W(r1b));
r2b = radioNew(20 + widgetWidthGet(W(r1b)), 35, "Radio 2b", 2);
guiAttach(W(w2), W(r2b));
r3b = radioNew(30 + widgetWidthGet(W(r1b)) + widgetWidthGet(W(r2b)), 35, "Radio 3b", 2);
guiAttach(W(w2), W(r3b));
radioSelectedSet(r1a);
radioSelectedSet(r2b);
tb1 = textboxNew(10, 60, 265, "Test Textbox");
textboxValueSet(tb1, "Really long text string to edit!");
guiAttach(W(w2), W(tb1));
tb2 = textboxNew(10, 85, 265, "Test Textbox");
textboxValueSet(tb2, "Short string.");
guiAttach(W(w2), W(tb2));
u1 = updownNew(10, 110, 0, 1024, 5, "UpDown");
guiAttach(W(w2), W(u1));
// Window 3
f1 = frameNew(10, 5, 175, 125, "Test Frame");
guiAttach(W(w3), W(f1));
b1 = buttonNew(0, 0, "Test Button", buttonClick);
guiAttach(W(f1), W(b1));
l1 = labelNew(10, 40, "Test Label");
guiAttach(W(f1), W(l1));
c1 = checkboxNew(10, 65, "Test Checkbox");
guiAttach(W(f1), W(c1));
// Window 4 - Terminal
t1 = terminalNew(0, 0, 80, 24);
guiAttach(W(w4), W(t1));
taskCreate(testTerminal, "terminalTest");
}
*/
void taskTestTagList(void *data) {
WindowT *w1 = NULL;
WindowT *w2 = NULL;
WindowT *w3 = NULL;
WindowT *w4 = NULL;
ButtonT *b1 = NULL;
LabelT *l1 = NULL;
CheckboxT *c1 = NULL;
RadioT *r1a = NULL;
RadioT *r2a = NULL;
RadioT *r3a = NULL;
RadioT *r1b = NULL;
RadioT *r2b = NULL;
RadioT *r3b = NULL;
PictureT *p1 = NULL;
FrameT *f1 = NULL;
TextboxT *tb1 = NULL;
TextboxT *tb2 = NULL;
UpdownT *u1 = NULL;
ListboxT *lb1 = NULL;
(void)data;
TagItemT ui[] = {
T_START,
T_WINDOW, O(w1),
T_TITLE, P("Window 1"),
T_X, 300, T_Y, 25, T_WIDTH, 300, T_HEIGHT, 200,
T_PICTURE, O(p1),
T_X, 0, T_Y, 0,
T_FILENAME, P("kanga.png"),
T_PICTURE, T_DONE,
T_LISTBOX, O(lb1),
T_TITLE, P("Listbox"),
T_X, 155, T_Y, 10, T_WIDTH, 120, T_HEIGHT, 140,
T_ITEM, P("One"),
T_ITEM, P("Two"),
T_ITEM, P("Three"),
T_ITEM, P("Four"),
T_ITEM, P("Five"),
T_ITEM, P("Six"),
T_ITEM, P("Seven"),
T_ITEM, P("Eight"),
T_ITEM, P("Nine"),
T_ITEM, P("Ten"),
T_STEP, 3,
T_LISTBOX, T_DONE,
T_WINDOW, T_DONE,
T_WINDOW, O(w2),
T_TITLE, P("Window 2"),
T_X, 150, T_Y, 150, T_WIDTH, 300, T_HEIGHT, 200,
T_RADIOBUTTON, O(r1a),
T_TITLE, P("Radio 1a"),
T_X, 10, T_Y, 10,
T_GROUP, 1,
T_SELECTED, 1,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r2a),
T_TITLE, P("Radio 2a"),
T_X, 20 + 80, T_Y, 10,
T_GROUP, 1,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r3a),
T_TITLE, P("Radio 3a"),
T_X, 30 + 80 * 2, T_Y, 10,
T_GROUP, 1,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r1b),
T_TITLE, P("Radio 1b"),
T_X, 10, T_Y, 35,
T_GROUP, 2,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r2b),
T_TITLE, P("Radio 2b"),
T_X, 20 + 80, T_Y, 35,
T_GROUP, 2,
T_SELECTED, 1,
T_RADIOBUTTON, T_DONE,
T_RADIOBUTTON, O(r3b),
T_TITLE, P("Radio 3b"),
T_X, 30 + 80 * 2, T_Y, 35,
T_GROUP, 2,
T_RADIOBUTTON, T_DONE,
T_TEXTBOX, O(tb1),
T_TITLE, P("Test Textbox"),
T_X, 10, T_Y, 60, T_WIDTH, 265,
T_VALUE, P("Really long text string to edit!"),
T_TEXTBOX, T_DONE,
T_TEXTBOX, O(tb2),
T_TITLE, P("Test Textbox"),
T_X, 10, T_Y, 85, T_WIDTH, 265,
T_VALUE, P("Short String."),
T_TEXTBOX, T_DONE,
T_UPDOWN, O(u1),
T_TITLE, P("UpDown"),
T_X, 10, T_Y, 120,
T_MINIMUM, 0, T_MAXIMUM, 1024, T_STEP, 5,
T_UPDOWN, T_DONE,
T_WINDOW, T_DONE,
T_WINDOW, O(w3),
T_TITLE, P("Window 3"),
T_X, 300, T_Y, 300, T_WIDTH, 300, T_HEIGHT, 200,
T_FRAME, O(f1),
T_TITLE, P("Test Frame"),
T_X, 10, T_Y, 5, T_WIDTH, 175, T_HEIGHT, 125,
T_BUTTON, O(b1),
T_TITLE, P("Test Button"),
T_X, 0, T_Y, 0,
T_CLICK, P(buttonClick),
T_BUTTON, T_DONE,
T_LABEL, O(l1),
T_TITLE, P("Test Label"),
T_X, 10, T_Y, 40,
T_LABEL, T_DONE,
T_CHECKBOX, O(c1),
T_TITLE, P("Test Checkbox"),
T_X, 10, T_Y, 65,
T_CHECKBOX, T_DONE,
T_FRAME, T_DONE,
T_WINDOW, T_DONE,
T_WINDOW, O(w4),
T_TITLE, P("Terminal"),
T_X, 10, T_Y, 10, T_WIDTH, 7 + 8 + (80 * 8), T_HEIGHT, 26 + 8 + (24 * 14),
T_TERMINAL, O(t1),
T_X, 0, T_Y, 0, T_WIDTH, 80, T_HEIGHT, 24,
T_TERMINAL, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(ui);
taskCreate(testTerminal, NULL);
}
static void testTerminal(void *data) {
FILE *in = NULL;
char *buffer = NULL;
uint16_t length = 0;
(void)data;
// Load ANSI file for terminal test.
in = fopen("kanga.ans", "rt");
fseek(in, 0, SEEK_END);
length = ftell(in);
fseek(in, 0, SEEK_SET);
buffer = (char *)malloc(length + 1);
fread(buffer, 1, length, in);
fclose(in);
buffer[length] = 0;
terminalStringPrint(t1, buffer);
free(buffer);
}
void widgetDebugDraw(WidgetT *widget, uint8_t debugToggle) {
size_t len = arrlenu(widget->children);
size_t i;
RectT r;
if (debugToggle) {
// Clipping region (blue)
guiWidgetBoundsDrawableOnScreenGet(widget, &r);
surfaceRectangleDraw(r.x, r.y, r.x + r.w, r.y + r.h, vbeColorMake(0, 0, 255));
} else {
// Widget border (red)
guiWidgetPositionOnScreenGet(widget, &r);
surfaceRectangleDraw(r.x, r.y, r.x + widget->pos.w, r.y + widget->pos.h, vbeColorMake(255, 0, 0));
}
if (len > 0) {
for (i=0; i<len; i++) {
widgetDebugDraw(widget->children[i], debugToggle);
}
}
}

36
client/src/test.h Normal file
View file

@ -0,0 +1,36 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef TEST_H
#define TEST_H
#include "os.h"
#include "terminal.h"
extern uint8_t lastKey;
void taskTestTagList(void *data);
void widgetDebugDraw(WidgetT *widget, uint8_t debugToggle);
#endif // TEST_H

View file

@ -307,7 +307,7 @@ typedef pthread_mutex_t mwMutex;
***********************************************************************/
static int mwInited = 0;
static int mwInfoWritten = 0;
static int mwInfoWritten = 1;
static int mwUseAtexit = 0;
static FILE* mwLog = NULL;
static int mwFlushing = 0;
@ -370,7 +370,7 @@ static mwMutex mwGlobalMutex;
static void mwAutoInit( void );
static FILE* mwLogR( void );
static void mwLogW( FILE* );
/* static */ void mwLogW( FILE* );
static int mwFlushR( void );
static void mwFlushW( int );
static void mwFlush( void );
@ -1531,7 +1531,7 @@ static FILE *mwLogR() {
return mwSTDERR;
}
static void mwLogW( FILE *p ) {
/* static */ void mwLogW( FILE *p ) {
mwLog = mwLogB1 = mwLogB2 = p;
}

97
client/src/welcome.c Normal file
View file

@ -0,0 +1,97 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#include "welcome.h"
#include "settings.h"
#include "taglist.h"
#include "task.h"
#include "window.h"
#include "picture.h"
#include "button.h"
static WindowT *winWelcome = NULL;
static PictureT *picLogo = NULL;
static ButtonT *btnQuit = NULL;
static ButtonT *btnSettings = NULL;
static ButtonT *btnConnect = NULL;
static void btnConnectClick(WidgetT *widget);
static void btnQuitClick(WidgetT *widget);
static void btnSettingsClick(WidgetT *widget);
static void btnConnectClick(WidgetT *widget) {
(void)widget;
}
static void btnQuitClick(WidgetT *widget) {
(void)widget;
guiStop();
}
static void btnSettingsClick(WidgetT *widget) {
(void)widget;
taskCreate(taskSettings, NULL);
guiDelete(D(winWelcome));
}
void taskWelcome(void *data) {
(void)data;
// 450x128 logo
TagItemT ui[] = {
T_START,
T_WINDOW, O(winWelcome),
T_TITLE, P("Welcome to KangaWorld!"),
T_WIDTH, 500, T_HEIGHT, 225,
T_PICTURE, O(picLogo),
T_FILENAME, P("logo.png"),
T_X, 18, T_Y, 18,
T_PICTURE, T_DONE,
T_BUTTON, O(btnQuit),
T_TITLE, P("Quit"),
T_X, 30, T_Y, 157,
T_CLICK, P(btnQuitClick),
T_BUTTON, T_DONE,
T_BUTTON, O(btnSettings),
T_TITLE, P("Settings"),
T_X, 201, T_Y, 157,
T_CLICK, P(btnSettingsClick),
T_BUTTON, T_DONE,
T_BUTTON, O(btnConnect),
T_TITLE, P("Connect"),
T_X, 379, T_Y, 157,
T_CLICK, P(btnConnectClick),
T_BUTTON, T_DONE,
T_WINDOW, T_DONE,
T_END
};
tagListRun(ui);
}

31
client/src/welcome.h Normal file
View file

@ -0,0 +1,31 @@
/*
* Kangaroo Punch MultiPlayer Game Server Mark II
* Copyright (C) 2020-2021 Scott Duensing
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
#ifndef WELCOME_H
#define WELCOME_H
#include "os.h"
void taskWelcome(void *data);
#endif // WELCOME_H