Message Box added to GUI. Connection code and timers are having issues.
This commit is contained in:
parent
eb9c13d5b2
commit
a4a8534aa6
31 changed files with 739 additions and 72 deletions
|
@ -27,7 +27,10 @@ CONFIG -= qt
|
|||
DESTDIR = $$OUT_PWD/bin
|
||||
SHARED = $$PWD/../shared
|
||||
|
||||
DOS_HEADERS =
|
||||
QMAKE_CFLAGS += -O0
|
||||
|
||||
DOS_HEADERS = \
|
||||
src/thirdparty/serial/serial.h
|
||||
|
||||
DOS_SOURCES = \
|
||||
src/thirdparty/serial/serial.c \
|
||||
|
@ -62,6 +65,7 @@ HEADERS = \
|
|||
$$SHARED/primes.h \
|
||||
src/config.h \
|
||||
$$SHARED/util.h \
|
||||
src/gui/msgbox.h \
|
||||
src/thirdparty/minicoro/minicoro.h \
|
||||
src/system/comport.h \
|
||||
src/settings.h \
|
||||
|
@ -103,7 +107,9 @@ SOURCES = \
|
|||
$$SHARED/thirdparty/ini/src/ini.c \
|
||||
src/config.c \
|
||||
$$SHARED/memory.c \
|
||||
src/gui/msgbox.c \
|
||||
src/settings.c \
|
||||
src/system/comport.c \
|
||||
src/system/surface.c \
|
||||
src/system/taglist.c \
|
||||
$$SHARED/util.c \
|
||||
|
|
BIN
client/data/IconError.png
(Stored with Git LFS)
Normal file
BIN
client/data/IconError.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/IconInformation.png
(Stored with Git LFS)
Normal file
BIN
client/data/IconInformation.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/IconMessage.png
(Stored with Git LFS)
Normal file
BIN
client/data/IconMessage.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/IconQuestion.png
(Stored with Git LFS)
Normal file
BIN
client/data/IconQuestion.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/IconWarning.png
(Stored with Git LFS)
Normal file
BIN
client/data/IconWarning.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/MessageBoxIcon.png
(Stored with Git LFS)
Normal file
BIN
client/data/MessageBoxIcon.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/mbie32.png
(Stored with Git LFS)
Normal file
BIN
client/data/mbie32.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/mbii32.png
(Stored with Git LFS)
Normal file
BIN
client/data/mbii32.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/mbim32.png
(Stored with Git LFS)
Normal file
BIN
client/data/mbim32.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/mbiq32.png
(Stored with Git LFS)
Normal file
BIN
client/data/mbiq32.png
(Stored with Git LFS)
Normal file
Binary file not shown.
BIN
client/data/mbiw32.png
(Stored with Git LFS)
Normal file
BIN
client/data/mbiw32.png
(Stored with Git LFS)
Normal file
Binary file not shown.
|
@ -65,11 +65,12 @@ 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);
|
||||
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);
|
||||
static WindowT *guiWindowFindTopChildrenProcess(WidgetT *widget);
|
||||
|
||||
|
||||
void guiAttach(WidgetT *parent, WidgetT *child) {
|
||||
|
@ -153,7 +154,12 @@ void guiDebugAreaShow(WidgetT *widget) {
|
|||
RectT r;
|
||||
|
||||
guiWidgetBoundsDrawableOnScreenGet(widget, &r);
|
||||
logWrite("%s: %dx%d\n", _magicDebugNames[widget->magic], r.w, r.h);
|
||||
logWrite("%s: Size %dx%d Area %dx%d TL %dx%d BR %dx%d\n",
|
||||
_magicDebugNames[widget->magic],
|
||||
widget->pos.w, widget->pos.h,
|
||||
r.w, r.h,
|
||||
widget->margin.x, widget->margin.y,
|
||||
widget->margin.w, widget->margin.h);
|
||||
}
|
||||
|
||||
|
||||
|
@ -191,7 +197,8 @@ void guiDelete(WidgetT **widget) {
|
|||
|
||||
|
||||
static void guiDeleteList(void) {
|
||||
WidgetT **w = NULL;
|
||||
WidgetT **w = NULL;
|
||||
WindowT *win = NULL;
|
||||
|
||||
while (arrlen(_guiDeleteList) > 0) {
|
||||
w = arrpop(_guiDeleteList);
|
||||
|
@ -200,6 +207,14 @@ static void guiDeleteList(void) {
|
|||
|
||||
arrfree(_guiDeleteList);
|
||||
_guiDeleteList = NULL;
|
||||
|
||||
// Is the top level window no longer active? If so, select it.
|
||||
win = guiWindowFindTop();
|
||||
if (win) {
|
||||
if (!GUI_GET_FLAG(W(win), WIDGET_FLAG_ACTIVE)) {
|
||||
windowActiveSet(win);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -686,3 +701,32 @@ void guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
WindowT *guiWindowFindTop(void) {
|
||||
if (guiRootGet() == NULL) return NULL;
|
||||
return guiWindowFindTopChildrenProcess(guiRootGet());
|
||||
}
|
||||
|
||||
|
||||
static WindowT *guiWindowFindTopChildrenProcess(WidgetT *widget) {
|
||||
size_t len = arrlenu(widget->children);
|
||||
size_t x;
|
||||
WindowT *top = NULL;
|
||||
WindowT *r = NULL;
|
||||
|
||||
// Is this a window?
|
||||
if (widget->magic == MAGIC_WINDOW) {
|
||||
top = (WindowT *)widget;
|
||||
}
|
||||
|
||||
// Check children.
|
||||
if (len > 0) {
|
||||
for (x=0; x<len; x++) {
|
||||
r = guiWindowFindTopChildrenProcess(widget->children[x]);
|
||||
if (r) top = r;
|
||||
}
|
||||
}
|
||||
|
||||
return top;
|
||||
}
|
||||
|
|
|
@ -213,6 +213,7 @@ void guiUserDataSet(WidgetT *widget, void *userData);
|
|||
void guiWidgetAndChildrenDirtySet(WidgetT *widget);
|
||||
void guiWidgetBoundsDrawableOnScreenGet(WidgetT *widget, RectT *bounds);
|
||||
void guiWidgetPositionOnScreenGet(WidgetT *widget, RectT *pos);
|
||||
WindowT *guiWindowFindTop(void);
|
||||
|
||||
|
||||
#endif // GUI_H
|
||||
|
|
219
client/src/gui/msgbox.c
Normal file
219
client/src/gui/msgbox.c
Normal file
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* 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 "msgbox.h"
|
||||
|
||||
#include "font.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "button.h"
|
||||
#include "label.h"
|
||||
#include "picture.h"
|
||||
|
||||
|
||||
#define WIN_MARGIN_TOP 26
|
||||
#define WIN_MARGIN_LEFT 7
|
||||
#define WIN_MARGIN_RIGHT 8
|
||||
#define WIN_MARGIN_BOTTOM 8
|
||||
|
||||
#define BTN_MARGIN_TOP 4
|
||||
#define BTN_MARGIN_LEFT 14
|
||||
#define BTN_MARGIN_RIGHT 14
|
||||
#define BTN_MARGIN_BOTTOM 4
|
||||
|
||||
#define MSG_PADDING 10
|
||||
|
||||
#define ICN_SIZE 32
|
||||
|
||||
|
||||
static msgBoxCallback cbOne = NULL;
|
||||
static msgBoxCallback cbTwo = NULL;
|
||||
static msgBoxCallback cbThree = NULL;
|
||||
|
||||
static WindowT *winDialog = NULL;
|
||||
static PictureT *picIcon = NULL;
|
||||
static LabelT *lblText = NULL;
|
||||
static ButtonT *btnOne = NULL;
|
||||
static ButtonT *btnTwo = NULL;
|
||||
static ButtonT *btnThree = NULL;
|
||||
|
||||
|
||||
static void btnMsgBox(WidgetT *widget);
|
||||
|
||||
|
||||
static char *iconFiles[MSGBOX_ICON_COUNT] = {
|
||||
"data/mbie32.png",
|
||||
"data/mbiw32.png",
|
||||
"data/mbii32.png",
|
||||
"data/mbim32.png",
|
||||
"data/mbiq32.png"
|
||||
};
|
||||
|
||||
|
||||
static void btnMsgBox(WidgetT *widget) {
|
||||
// Remove us from the display.
|
||||
guiDelete(D(winDialog));
|
||||
// Call whoever wanted called.
|
||||
if (widget == W(btnOne)) {
|
||||
if (cbOne) cbOne(MSGBOX_BUTTON_ONE);
|
||||
}
|
||||
if (widget == W(btnTwo)) {
|
||||
if (cbTwo) cbTwo(MSGBOX_BUTTON_TWO);
|
||||
}
|
||||
if (widget == W(btnThree)) {
|
||||
if (cbThree) cbThree(MSGBOX_BUTTON_THREE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void msgBoxOne(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne) {
|
||||
return msgBoxThree(title, icon, message, buttonOne, callbackOne, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
|
||||
void msgBoxThree(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne, char *buttonTwo, msgBoxCallback callbackTwo, char *buttonThree, msgBoxCallback callbackThree) {
|
||||
uint16_t w = 0;
|
||||
uint16_t h = 0;
|
||||
uint16_t x = 0;
|
||||
uint16_t y = 0;
|
||||
uint16_t t = 0;
|
||||
uint16_t textH = 0;
|
||||
uint16_t textW = 0;
|
||||
uint16_t iconW = 0;
|
||||
uint16_t newW = 0;
|
||||
uint16_t cursorH = 0;
|
||||
char *token = NULL;
|
||||
char *text = NULL;
|
||||
|
||||
// Null these for later.
|
||||
btnOne = NULL;
|
||||
btnTwo = NULL;
|
||||
btnThree = NULL;
|
||||
|
||||
// Remember callbacks for later.
|
||||
cbOne = callbackOne;
|
||||
cbTwo = callbackTwo;
|
||||
cbThree = callbackThree;
|
||||
|
||||
// Calculate size of dialog box window.
|
||||
|
||||
// Initial minimum window width is the left and right margins + font width * (title length + 3).
|
||||
w = WIN_MARGIN_LEFT + WIN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * (strlen(title) + 3));
|
||||
|
||||
// Initial minimum window height is the top and bottom margins + font height + button height + (padding * 2).
|
||||
h = WIN_MARGIN_TOP + WIN_MARGIN_BOTTOM + fontHeightGet(_guiFont) + (BTN_MARGIN_TOP + BTN_MARGIN_BOTTOM + fontHeightGet(_guiFont)) + (MSG_PADDING * 2);
|
||||
|
||||
// Count lines of text and add up height. Find widest line.
|
||||
text = strdup(message);
|
||||
token = strtok(text, "\n");
|
||||
while (token) {
|
||||
textH += fontHeightGet(_guiFont);
|
||||
if (strlen(token) > textW) {
|
||||
textW = strlen(token);
|
||||
}
|
||||
token = strtok(NULL, "\n");
|
||||
}
|
||||
free(text);
|
||||
textW *= fontWidthGet(_guiFont);
|
||||
|
||||
// Initial cursor move and window sizing are based on text height.
|
||||
cursorH = textH;
|
||||
|
||||
// Is there an icon?
|
||||
if (icon > MSGBOX_ICON_NONE && icon < MSGBOX_ICON_COUNT) {
|
||||
// Is the icon taller than the message text?
|
||||
if (ICN_SIZE > textH) {
|
||||
// Use icon height.
|
||||
cursorH = ICN_SIZE;
|
||||
}
|
||||
iconW = ICN_SIZE + MSG_PADDING;
|
||||
}
|
||||
|
||||
// Add icon and/or text height to window.
|
||||
h += cursorH;
|
||||
|
||||
// Do we need to make the dialog wider to contain the text and icon?
|
||||
newW = WIN_MARGIN_LEFT + WIN_MARGIN_RIGHT + iconW + textW + (MSG_PADDING * 2); // Only 2 here because iconW includes one.
|
||||
if (newW > w) w = newW;
|
||||
|
||||
// Do we need to make the dialog wider to contain the buttons?
|
||||
newW = WIN_MARGIN_LEFT + WIN_MARGIN_RIGHT + MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonOne));
|
||||
if (buttonTwo) newW += MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonTwo));
|
||||
if (buttonThree) newW += MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonThree));
|
||||
if (newW > w) w = newW;
|
||||
|
||||
// Draw dialog.
|
||||
|
||||
h -= 5; // Height is off for some reason. At least, to me, it doesn't look right.
|
||||
winDialog = windowNew(vbeDisplayWidthGet() / 2 - w / 2, vbeDisplayHeightGet() / 2 - h / 2, w, h, title);
|
||||
guiAttach(guiRootGet(), W(winDialog));
|
||||
|
||||
// Initial x cursor is the (implied window left margin +) padding
|
||||
x = MSG_PADDING;
|
||||
|
||||
// Initial y cursor is the (implied window top margin +) padding
|
||||
y = MSG_PADDING;
|
||||
|
||||
// Load proper icon, if desired.
|
||||
if (icon > MSGBOX_ICON_NONE && icon < MSGBOX_ICON_COUNT) {
|
||||
picIcon = pictureNew(x, y, iconFiles[icon - 1]);
|
||||
guiAttach(W(winDialog), W(picIcon));
|
||||
}
|
||||
|
||||
// Draw message text.
|
||||
t = y;
|
||||
x += iconW;
|
||||
text = strdup(message);
|
||||
token = strtok(text, "\n");
|
||||
while (token) {
|
||||
lblText = labelNew(x, t, token);
|
||||
guiAttach(W(winDialog), W(lblText));
|
||||
t += fontHeightGet(_guiFont);
|
||||
token = strtok(NULL, "\n");
|
||||
}
|
||||
free(text);
|
||||
|
||||
// Move to where buttons belong.
|
||||
x = w - (WIN_MARGIN_LEFT + WIN_MARGIN_RIGHT + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonOne)));
|
||||
y += cursorH + MSG_PADDING;
|
||||
|
||||
// We always have at least one button.
|
||||
btnOne = buttonNew(x, y, buttonOne, btnMsgBox);
|
||||
guiAttach(W(winDialog), W(btnOne));
|
||||
|
||||
// Two buttons?
|
||||
if (buttonTwo) {
|
||||
x -= (MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonTwo)));
|
||||
btnTwo = buttonNew(x, y, buttonTwo, btnMsgBox);
|
||||
guiAttach(W(winDialog), W(btnTwo));
|
||||
}
|
||||
|
||||
// Three buttons?
|
||||
if (buttonThree) {
|
||||
x -= (MSG_PADDING + BTN_MARGIN_LEFT + BTN_MARGIN_RIGHT + (fontWidthGet(_guiFont) * strlen(buttonThree)));
|
||||
btnThree = buttonNew(x, y, buttonThree, btnMsgBox);
|
||||
guiAttach(W(winDialog), W(btnThree));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void msgBoxTwo(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne, char *buttonTwo, msgBoxCallback callbackTwo) {
|
||||
return msgBoxThree(title, icon, message, buttonOne, callbackOne, buttonTwo, callbackTwo, NULL, NULL);
|
||||
}
|
57
client/src/gui/msgbox.h
Normal file
57
client/src/gui/msgbox.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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 MSGBOX_H
|
||||
#define MSGBOX_H
|
||||
|
||||
|
||||
#include "os.h"
|
||||
#include "widget.h"
|
||||
|
||||
|
||||
enum MsgBoxIconE {
|
||||
MSGBOX_ICON_NONE = 0,
|
||||
MSGBOX_ICON_ERROR,
|
||||
MSGBOX_ICON_WARNING,
|
||||
MSGBOX_ICON_INFORMATION,
|
||||
MSGBOX_ICON_MESSAGE,
|
||||
MSGBOX_ICON_QUESTION,
|
||||
MSGBOX_ICON_COUNT
|
||||
};
|
||||
|
||||
enum MsgBoxButtonE {
|
||||
MSGBOX_BUTTON_ONE = 0,
|
||||
MSGBOX_BUTTON_TWO,
|
||||
MSGBOX_BUTTON_THREE,
|
||||
MSGBOX_BUTTON_COUNT
|
||||
};
|
||||
|
||||
|
||||
typedef enum MsgBoxIconE MsgBoxIconT;
|
||||
typedef enum MsgBoxButtonE MsgBoxButtonT;
|
||||
typedef void (*msgBoxCallback)(MsgBoxButtonT button);
|
||||
|
||||
|
||||
void msgBoxOne(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne);
|
||||
void msgBoxThree(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne, char *buttonTwo, msgBoxCallback callbackTwo, char *buttonThree, msgBoxCallback callbackThree);
|
||||
void msgBoxTwo(char *title, MsgBoxIconT icon, char *message, char *buttonOne, msgBoxCallback callbackOne, char *buttonTwo, msgBoxCallback callbackTwo);
|
||||
|
||||
|
||||
#endif // MSGBOX_H
|
|
@ -289,7 +289,7 @@ static void textboxPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
|
|||
free(draw);
|
||||
|
||||
// Draw cursor.
|
||||
if (guiFocusGet() == widget && timerQuarterSecondOn) {
|
||||
if (guiFocusGet() == widget && _timerQuarterSecondOn) {
|
||||
caretPos = textX + fontWidthGet(_guiFont) * t->caret;
|
||||
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], caretPos, textY);
|
||||
}
|
||||
|
|
|
@ -307,7 +307,7 @@ static void updownPaint(WidgetT *widget, uint8_t enabled, RectT pos) {
|
|||
fontRender(_guiFont, draw, _guiColor[COLOR_UPDOWN_TEXT], _guiColor[COLOR_UPDOWN_BACKGROUND], textX, textY);
|
||||
|
||||
// Draw cursor.
|
||||
if (guiFocusGet() == widget && timerQuarterSecondOn) {
|
||||
if (guiFocusGet() == widget && _timerQuarterSecondOn) {
|
||||
textX += (strlen(draw) - 1) * fontWidthGet(_guiFont);
|
||||
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], textX, textY);
|
||||
}
|
||||
|
|
|
@ -76,6 +76,26 @@ WidgetT *widgetInit(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint
|
|||
}
|
||||
|
||||
|
||||
uint16_t widgetMarginBottomGet(WidgetT *widget) {
|
||||
return widget->margin.h;
|
||||
}
|
||||
|
||||
|
||||
uint16_t widgetMarginLeftGet(WidgetT *widget) {
|
||||
return widget->margin.x;
|
||||
}
|
||||
|
||||
|
||||
uint16_t widgetMarginRightGet(WidgetT *widget){
|
||||
return widget->margin.w;
|
||||
}
|
||||
|
||||
|
||||
uint16_t widgetMarginTopGet(WidgetT *widget) {
|
||||
return widget->margin.y;
|
||||
}
|
||||
|
||||
|
||||
WidgetT *widgetNew(uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2) {
|
||||
WidgetT *widget = (WidgetT *)malloc(sizeof(WidgetT));
|
||||
|
||||
|
|
|
@ -70,6 +70,10 @@ uint8_t widgetEnableGet(WidgetT *widget);
|
|||
void widgetEnableSet(WidgetT *widget, uint8_t enabled);
|
||||
uint16_t widgetHeightGet(WidgetT *widget);
|
||||
WidgetT *widgetInit(WidgetT *widget, uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2);
|
||||
uint16_t widgetMarginBottomGet(WidgetT *widget);
|
||||
uint16_t widgetMarginLeftGet(WidgetT *widget);
|
||||
uint16_t widgetMarginRightGet(WidgetT *widget);
|
||||
uint16_t widgetMarginTopGet(WidgetT *widget);
|
||||
WidgetT *widgetNew(uint8_t magic, uint16_t x, uint16_t y, uint16_t w, uint16_t h, uint16_t marginX, uint16_t marginY, uint16_t marginX2, uint16_t marginY2);
|
||||
uint8_t widgetVisibleGet(WidgetT *widget);
|
||||
void widgetVisibleSet(WidgetT *widget, uint8_t enabled);
|
||||
|
|
|
@ -443,6 +443,7 @@ static void processNetworkEvent(void) {
|
|||
case ENET_EVENT_TYPE_DISCONNECT_TIMEOUT:
|
||||
_connected = 0;
|
||||
_modemCommandMode = 1;
|
||||
comAddToBuffer("\13NO CARRIER\13", 12);
|
||||
break;
|
||||
|
||||
default:
|
||||
|
|
|
@ -55,17 +55,16 @@ typedef struct PortS {
|
|||
} PortT;
|
||||
|
||||
|
||||
static WindowT *winDetecting;
|
||||
static LabelT *lblOneMoment;
|
||||
|
||||
static WindowT *winSettings;
|
||||
static FrameT *frmComPorts;
|
||||
static FrameT *frmServer;
|
||||
static ButtonT *btnOkay;
|
||||
static TextboxT *txtServer;
|
||||
static UpdownT *updPort;
|
||||
|
||||
static PortT port[4];
|
||||
static WindowT *winDetecting;
|
||||
static LabelT *lblOneMoment;
|
||||
static WindowT *winSettings;
|
||||
static FrameT *frmComPorts;
|
||||
static FrameT *frmServer;
|
||||
static ButtonT *btnOkay;
|
||||
static TextboxT *txtServer;
|
||||
static UpdownT *updPort;
|
||||
static PortT port[4];
|
||||
static widgetCallback done;
|
||||
|
||||
|
||||
static void btnOkayClick(WidgetT *widget);
|
||||
|
@ -90,9 +89,9 @@ static void btnOkayClick(WidgetT *widget) {
|
|||
_configData.serverHost = strdup(textboxValueGet(txtServer));
|
||||
_configData.serverPort = updownValueGet(updPort);
|
||||
|
||||
// Return to welcome dialog.
|
||||
taskCreate(taskWelcome, NULL);
|
||||
// Return to calling routine.
|
||||
guiDelete(D(winSettings));
|
||||
done(NULL);
|
||||
}
|
||||
|
||||
|
||||
|
@ -101,10 +100,9 @@ void taskSettings(void *data) {
|
|||
int32_t rc;
|
||||
uint32_t len;
|
||||
char buffer[1024];
|
||||
uint8_t quarterSeconds = 0;
|
||||
uint8_t selected = 1;
|
||||
|
||||
(void)data;
|
||||
done = (widgetCallback)data;
|
||||
|
||||
TagItemT uiDetecting[] = {
|
||||
T_START,
|
||||
|
@ -126,15 +124,10 @@ void taskSettings(void *data) {
|
|||
for (int x=0; x<4; x++) {
|
||||
rc = comOpen(x, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
|
||||
if (rc == SER_SUCCESS) {
|
||||
snprintf(buffer, 1024, "%s%c", "AT+SOCK1", 13);
|
||||
snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
|
||||
comWrite(x, buffer, strlen(buffer));
|
||||
// Wait a second.
|
||||
quarterSeconds = 0;
|
||||
while (quarterSeconds < 5) {
|
||||
taskYield();
|
||||
if (timerQuarterSecondTick) quarterSeconds++;
|
||||
}
|
||||
len = comRead(x, buffer, 1024);
|
||||
// timerQuarterSecondsWait(4);
|
||||
len = comRead(x, buffer, 1023);
|
||||
buffer[len] = 0;
|
||||
if (strstr(buffer, "OK")) {
|
||||
snprintf(port[x].title, TITLE_LEN - 1, "COM%d - SoftModem Found!", x + 1);
|
||||
|
|
80
client/src/system/comport.c
Normal file
80
client/src/system/comport.c
Normal file
|
@ -0,0 +1,80 @@
|
|||
/*
|
||||
* 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 "comport.h"
|
||||
#include "timer.h"
|
||||
#include "task.h"
|
||||
|
||||
|
||||
int comReceiveBufferFlush(int com) {
|
||||
char buffer[256];
|
||||
int result = 1;
|
||||
|
||||
while (result > 0) {
|
||||
result = comRead(com, buffer, 255);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
int comWaitWithTimeout(int com, char *buffer, int len, int quarterSeconds, char *expecting) {
|
||||
int r;
|
||||
int quarterTicks = 0;
|
||||
int count = 0;
|
||||
int bufferIndex = 0;
|
||||
char data[2];
|
||||
|
||||
while (quarterTicks <= quarterSeconds) {
|
||||
r = comRead(com, data, 1);
|
||||
if (r == 1) {
|
||||
logWrite("Byte\n");
|
||||
buffer[bufferIndex++] = data[0];
|
||||
buffer[bufferIndex] = 0;
|
||||
if (data[0] == expecting[count]) {
|
||||
logWrite("Expect\n");
|
||||
count++;
|
||||
if (count == (int)strlen(expecting)) {
|
||||
// Found our expect.
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
count = 0;
|
||||
}
|
||||
if (bufferIndex == len - 1) {
|
||||
// Out of buffer.
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
sprintf(data, "%c", 0);
|
||||
}
|
||||
if (_timerQuarterSecondTick) {
|
||||
quarterTicks++;
|
||||
logWrite("Tick\n");
|
||||
}
|
||||
taskYield();
|
||||
}
|
||||
|
||||
if (count == (int)strlen(expecting)) {
|
||||
return bufferIndex;
|
||||
}
|
||||
|
||||
return -bufferIndex;
|
||||
}
|
|
@ -52,4 +52,8 @@ int comWrite(int com, const char *data, int len);
|
|||
#endif
|
||||
|
||||
|
||||
int comReceiveBufferFlush(int com);
|
||||
int comWaitWithTimeout(int com, char *buffer, int len, int quarterSeconds, char *expecting);
|
||||
|
||||
|
||||
#endif // COMPORT_H
|
||||
|
|
|
@ -65,6 +65,7 @@ long biostime(int cmd, long newtime);
|
|||
|
||||
// Now our headers.
|
||||
#include "log.h"
|
||||
#include "util.h"
|
||||
|
||||
|
||||
// Allocation helpers.
|
||||
|
|
|
@ -23,9 +23,8 @@
|
|||
//#define MCO_DEFAULT_STACK_SIZE 114688 // Default is 57344
|
||||
#include "thirdparty/minicoro/minicoro.h"
|
||||
|
||||
|
||||
#include "array.h"
|
||||
#include "task.h"
|
||||
#include "array.h"
|
||||
|
||||
|
||||
typedef struct TaskS {
|
||||
|
@ -111,6 +110,6 @@ void taskStartup(void) {
|
|||
}
|
||||
|
||||
|
||||
void taskYield(void) {
|
||||
void __attribute__ ((noinline)) taskYield(void) {
|
||||
mco_yield(mco_running());
|
||||
}
|
||||
|
|
|
@ -19,6 +19,8 @@
|
|||
|
||||
|
||||
#include "timer.h"
|
||||
#include "task.h"
|
||||
#include "gui.h"
|
||||
|
||||
|
||||
#define SECONDS_IN_DAY 86400
|
||||
|
@ -26,18 +28,18 @@
|
|||
#define TICKS_PER_DAY (SECONDS_IN_DAY * TICKS_PER_SECOND)
|
||||
|
||||
|
||||
uint8_t timerQuarterSecondTick = 0;
|
||||
uint8_t timerHalfSecondTick = 0;
|
||||
uint8_t timerSecondTick = 0;
|
||||
volatile uint8_t _timerQuarterSecondTick = 0;
|
||||
volatile uint8_t _timerHalfSecondTick = 0;
|
||||
volatile uint8_t _timerSecondTick = 0;
|
||||
|
||||
uint8_t timerQuarterSecondOn = 0;
|
||||
uint8_t timerHalfSecondOn = 0;
|
||||
uint8_t timerSecondOn = 0;
|
||||
volatile uint8_t _timerQuarterSecondOn = 0;
|
||||
volatile uint8_t _timerHalfSecondOn = 0;
|
||||
volatile uint8_t _timerSecondOn = 0;
|
||||
|
||||
|
||||
static long _timerLast = 0;
|
||||
static uint8_t _timerHalfSecond = 2;
|
||||
static uint8_t _timerSecond = 2;
|
||||
static volatile long timerLast = 0;
|
||||
static volatile uint8_t timerHalfSecond = 2;
|
||||
static volatile uint8_t timerSecond = 2;
|
||||
|
||||
|
||||
void timerShutdown(void) {
|
||||
|
@ -46,7 +48,7 @@ void timerShutdown(void) {
|
|||
|
||||
|
||||
void timerStartup(void) {
|
||||
_timerLast = biostime(0, 0);
|
||||
timerLast = biostime(0, 0);
|
||||
}
|
||||
|
||||
|
||||
|
@ -57,40 +59,55 @@ void timerUpdate(void) {
|
|||
now = biostime(0, 0);
|
||||
|
||||
// Reset ticks.
|
||||
timerQuarterSecondTick = 0;
|
||||
timerHalfSecondTick = 0;
|
||||
timerSecondTick = 0;
|
||||
_timerQuarterSecondTick = 0;
|
||||
_timerHalfSecondTick = 0;
|
||||
_timerSecondTick = 0;
|
||||
|
||||
// Ensure we haven't rolled past midnight between calls.
|
||||
if (now >= _timerLast) {
|
||||
delta = now - _timerLast;
|
||||
if (now >= timerLast) {
|
||||
delta = now - timerLast;
|
||||
} else {
|
||||
// Compensate for midnight rollover.
|
||||
delta = (now + TICKS_PER_DAY) - _timerLast;
|
||||
delta = (now + TICKS_PER_DAY) - timerLast;
|
||||
}
|
||||
|
||||
// Everything ticks off the quarter second.
|
||||
if (delta > TICKS_PER_SECOND * 0.25) {
|
||||
_timerLast = now;
|
||||
timerLast = now;
|
||||
|
||||
// Quarter Second timer.
|
||||
timerQuarterSecondOn = !timerQuarterSecondOn;
|
||||
timerQuarterSecondTick = 1;
|
||||
_timerQuarterSecondOn = !_timerQuarterSecondOn;
|
||||
_timerQuarterSecondTick = 1;
|
||||
|
||||
// Half Second timer.
|
||||
if (--_timerHalfSecond == 0) {
|
||||
_timerHalfSecond = 2;
|
||||
timerHalfSecondOn = !timerHalfSecondOn;
|
||||
timerHalfSecondTick = 1;
|
||||
if (--timerHalfSecond == 0) {
|
||||
timerHalfSecond = 2;
|
||||
_timerHalfSecondOn = !_timerHalfSecondOn;
|
||||
_timerHalfSecondTick = 1;
|
||||
|
||||
// Second timer
|
||||
if (--_timerSecond == 0) {
|
||||
_timerSecond = 2;
|
||||
timerSecondOn = !timerSecondOn;
|
||||
timerSecondTick = 1;
|
||||
if (--timerSecond == 0) {
|
||||
timerSecond = 2;
|
||||
_timerSecondOn = !_timerSecondOn;
|
||||
_timerSecondTick = 1;
|
||||
} // Second.
|
||||
|
||||
} // Half Second.
|
||||
|
||||
} // Quarter Second.
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void timerQuarterSecondsWait(u_int8_t quarterSeconds) {
|
||||
uint8_t counter = 0;
|
||||
|
||||
while (counter <= quarterSeconds && !guiHasStopped()) {
|
||||
if (_timerQuarterSecondTick) {
|
||||
counter++;
|
||||
}
|
||||
logWrite("Waiting %d of %d\n", counter, quarterSeconds);
|
||||
taskYield();
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
|
|
@ -25,18 +25,19 @@
|
|||
#include "os.h"
|
||||
|
||||
|
||||
extern uint8_t timerQuarterSecondTick;
|
||||
extern uint8_t timerHalfSecondTick;
|
||||
extern uint8_t timerSecondTick;
|
||||
extern volatile uint8_t _timerQuarterSecondTick;
|
||||
extern volatile uint8_t _timerHalfSecondTick;
|
||||
extern volatile uint8_t _timerSecondTick;
|
||||
|
||||
extern uint8_t timerQuarterSecondOn;
|
||||
extern uint8_t timerHalfSecondOn;
|
||||
extern uint8_t timerSecondOn;
|
||||
extern volatile uint8_t _timerQuarterSecondOn;
|
||||
extern volatile uint8_t _timerHalfSecondOn;
|
||||
extern volatile uint8_t _timerSecondOn;
|
||||
|
||||
|
||||
void timerShutdown(void);
|
||||
void timerStartup(void);
|
||||
void timerUpdate(void);
|
||||
//void timerQuarterSecondsWait(u_int8_t quarterSeconds);
|
||||
|
||||
|
||||
#endif // TIMER_H
|
||||
|
|
|
@ -24,40 +24,175 @@
|
|||
#include "taglist.h"
|
||||
#include "task.h"
|
||||
#include "config.h"
|
||||
#include "comport.h"
|
||||
#include "timer.h"
|
||||
|
||||
#include "window.h"
|
||||
#include "picture.h"
|
||||
#include "button.h"
|
||||
#include "msgbox.h"
|
||||
|
||||
|
||||
static WindowT *winWelcome = NULL;
|
||||
static PictureT *picLogo = NULL;
|
||||
static PictureT *picInit = NULL;
|
||||
static PictureT *picDialing = NULL;
|
||||
static PictureT *picConnect = NULL;
|
||||
static ButtonT *btnQuit = NULL;
|
||||
static ButtonT *btnSettings = NULL;
|
||||
static ButtonT *btnConnect = NULL;
|
||||
|
||||
|
||||
static void btnConnectClick(WidgetT *widget);
|
||||
static void btnMsgBox(MsgBoxButtonT button);
|
||||
static void btnMsgBoxQuit(MsgBoxButtonT button);
|
||||
static void btnQuitClick(WidgetT *widget);
|
||||
static void btnSettingsClick(WidgetT *widget);
|
||||
static void setButtons(uint8_t enabled);
|
||||
static void settingsFinished(WidgetT *widget);
|
||||
|
||||
|
||||
static void btnMsgBox(MsgBoxButtonT button) {
|
||||
(void)button;
|
||||
|
||||
// Re-enable buttons.
|
||||
setButtons(1);
|
||||
|
||||
// Reset to Welcome image.
|
||||
widgetVisibleSet(W(picLogo), 1);
|
||||
widgetVisibleSet(W(picInit), 0);
|
||||
widgetVisibleSet(W(picDialing), 0);
|
||||
widgetVisibleSet(W(picConnect), 0);
|
||||
}
|
||||
|
||||
|
||||
static void btnMsgBoxQuit(MsgBoxButtonT button) {
|
||||
if (button == MSGBOX_BUTTON_ONE) {
|
||||
guiStop();
|
||||
} else {
|
||||
setButtons(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void btnConnectClick(WidgetT *widget) {
|
||||
uint32_t r;
|
||||
uint32_t len;
|
||||
char buffer[1024];
|
||||
int8_t timeout = 7 * 4; // Seven seconds (of quarter seconds) to connect to server.
|
||||
uint16_t count = 0;
|
||||
uint8_t connected = 0;
|
||||
char *banner = "KPMPGSMKII";
|
||||
|
||||
(void)widget;
|
||||
|
||||
// Ghost all buttons.
|
||||
widgetEnableSet(W(btnConnect), 0);
|
||||
widgetEnableSet(W(btnSettings), 0);
|
||||
widgetEnableSet(W(btnQuit), 0);
|
||||
|
||||
// Hide welcome banner, show init.
|
||||
widgetVisibleSet(W(picLogo), 0);
|
||||
widgetVisibleSet(W(picInit), 1);
|
||||
taskYield();
|
||||
|
||||
// Open COM port.
|
||||
r = comOpen(_configData.serialCom - 1, 57600L, 8, 'n', 1, SER_HANDSHAKING_RTSCTS);
|
||||
if (r != SER_SUCCESS) {
|
||||
msgBoxOne("COM Problem", MSGBOX_ICON_ERROR, "Unable to open COM port!\nPlease check settings.", "Okay", btnMsgBox);
|
||||
return;
|
||||
}
|
||||
logWrite("COM open\n");
|
||||
|
||||
// Send a CR to clear anything in the modem.
|
||||
snprintf(buffer, 1023, "%c", 13);
|
||||
comWrite(_configData.serialCom - 1, buffer, strlen(buffer));
|
||||
logWrite("CR sent\n");
|
||||
// Wait roughly a second.
|
||||
comWaitWithTimeout(_configData.serialCom - 1, buffer, 1023, 4, "weExpectNothing");
|
||||
//uint32_t dumbThing = timerQuarterSecondsWait(4);
|
||||
logWrite("Wait over\n");
|
||||
// Flush COM port.
|
||||
comReceiveBufferFlush(_configData.serialCom - 1);
|
||||
logWrite("Port flushed\n");
|
||||
|
||||
// Send actual init
|
||||
snprintf(buffer, 1023, "%s%c", "AT+SOCK1", 13);
|
||||
comWrite(_configData.serialCom - 1, buffer, strlen(buffer));
|
||||
// Wait roughly a second.
|
||||
// timerQuarterSecondsWait(4);
|
||||
// Read COM port & check for OK.
|
||||
len = comRead(_configData.serialCom - 1, buffer, 1023);
|
||||
buffer[len] = 0;
|
||||
if (!strstr(buffer, "OK")) {
|
||||
comClose(_configData.serialCom - 1);
|
||||
msgBoxOne("Modem Problem", MSGBOX_ICON_ERROR, "Modem does not support ENET!\nPlease check settings.", "Okay", btnMsgBox);
|
||||
return;
|
||||
}
|
||||
|
||||
// Show dialing, dial service.
|
||||
widgetVisibleSet(W(picDialing), 1);
|
||||
taskYield();
|
||||
snprintf(buffer, 1023, "ATDT%s:%d%c", _configData.serverHost, _configData.serverPort, 13);
|
||||
comWrite(_configData.serialCom - 1, buffer, strlen(buffer));
|
||||
while (timeout > 0 && connected == 0) {
|
||||
len = comRead(_configData.serialCom - 1, buffer, 1);
|
||||
// Did we get a character?
|
||||
if (len == 1) {
|
||||
// Is it the next we expect in the server banner?
|
||||
if (buffer[0] == banner[count]) {
|
||||
count++;
|
||||
} else {
|
||||
count = 0;
|
||||
}
|
||||
// Are we connected?
|
||||
if (count == strlen(banner)) {
|
||||
connected = 1;
|
||||
}
|
||||
}
|
||||
// Tick timeout.
|
||||
if (_timerQuarterSecondTick) timeout--;
|
||||
taskYield();
|
||||
}
|
||||
// timerQuarterSecondsWait(4);
|
||||
comReceiveBufferFlush(_configData.serialCom - 1);
|
||||
// Did we connect?
|
||||
if (!connected) {
|
||||
comClose(_configData.serialCom - 1);
|
||||
msgBoxOne("No Connection", MSGBOX_ICON_INFORMATION, "Unable to connect to server!\nPlease check settings or try later.", "Okay", btnMsgBox);
|
||||
return;
|
||||
}
|
||||
|
||||
// Connected! Show icon and negotiate session.
|
||||
widgetVisibleSet(W(picConnect), 1);
|
||||
taskYield();
|
||||
}
|
||||
|
||||
|
||||
static void btnQuitClick(WidgetT *widget) {
|
||||
(void)widget;
|
||||
guiStop();
|
||||
setButtons(0);
|
||||
msgBoxTwo("Quit?", MSGBOX_ICON_QUESTION, "Exit to DOS?", "Okay", btnMsgBoxQuit, "Cancel", btnMsgBoxQuit);
|
||||
}
|
||||
|
||||
|
||||
static void btnSettingsClick(WidgetT *widget) {
|
||||
(void)widget;
|
||||
taskCreate(taskSettings, NULL);
|
||||
guiDelete(D(winWelcome));
|
||||
setButtons(0);
|
||||
taskCreate(taskSettings, settingsFinished);
|
||||
}
|
||||
|
||||
|
||||
void setButtons(uint8_t enabled) {
|
||||
widgetEnableSet(W(btnConnect), (_configData.serialCom > 0 && strlen(_configData.serverHost) > 2) ? enabled : 0);
|
||||
widgetEnableSet(W(btnSettings), enabled);
|
||||
widgetEnableSet(W(btnQuit), enabled);
|
||||
}
|
||||
|
||||
|
||||
static void settingsFinished(WidgetT *widget) {
|
||||
(void)widget;
|
||||
setButtons(1);
|
||||
}
|
||||
|
||||
|
||||
|
@ -72,10 +207,28 @@ void taskWelcome(void *data) {
|
|||
T_WINDOW, O(winWelcome),
|
||||
T_TITLE, P("Welcome to KangaWorld!"),
|
||||
T_WIDTH, 500, T_HEIGHT, 225,
|
||||
|
||||
T_PICTURE, O(picLogo),
|
||||
T_FILENAME, P("data/logo.png"),
|
||||
T_X, 18, T_Y, 18,
|
||||
T_PICTURE, T_DONE,
|
||||
|
||||
T_PICTURE, O(picInit),
|
||||
T_FILENAME, P("data/dinit.png"),
|
||||
T_X, 18, T_Y, 18,
|
||||
T_VISIBLE, T_FALSE,
|
||||
T_PICTURE, T_DONE,
|
||||
T_PICTURE, O(picDialing),
|
||||
T_FILENAME, P("data/ddialing.png"),
|
||||
T_X, 179, T_Y, 18,
|
||||
T_VISIBLE, T_FALSE,
|
||||
T_PICTURE, T_DONE,
|
||||
T_PICTURE, O(picConnect),
|
||||
T_FILENAME, P("data/dconnect.png"),
|
||||
T_X, 339, T_Y, 18,
|
||||
T_VISIBLE, T_FALSE,
|
||||
T_PICTURE, T_DONE,
|
||||
|
||||
T_BUTTON, O(btnQuit),
|
||||
T_TITLE, P("Quit"),
|
||||
T_X, 30, T_Y, 157,
|
||||
|
@ -92,6 +245,7 @@ void taskWelcome(void *data) {
|
|||
T_CLICK, P(btnConnectClick),
|
||||
T_ENABLED, (_configData.serialCom > 0 && strlen(_configData.serverHost) > 2) ? T_TRUE : T_FALSE,
|
||||
T_BUTTON, T_DONE,
|
||||
|
||||
T_WINDOW, T_DONE,
|
||||
T_END
|
||||
};
|
||||
|
|
|
@ -62,3 +62,34 @@ void utilDie(const char *why, ...) {
|
|||
logWrite("DIE: %s", msg);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
char *utilCreateString(char *format, ...) {
|
||||
va_list args;
|
||||
char *string;
|
||||
|
||||
va_start(args, format);
|
||||
string = utilCreateStringVArgs(format, args);
|
||||
va_end(args);
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
|
||||
__attribute__((__format__(__printf__, 1, 0)))
|
||||
char *utilCreateStringVArgs(char *format, va_list args) {
|
||||
va_list argsCopy;
|
||||
int32_t size = 0;
|
||||
char *buffer = NULL;
|
||||
|
||||
va_copy(argsCopy, args);
|
||||
size = vsnprintf(NULL, 0, format, argsCopy) + 1;
|
||||
va_end(argsCopy);
|
||||
buffer = calloc(1, (size_t)size);
|
||||
if (buffer) {
|
||||
vsnprintf(buffer, (size_t)size, format, args);
|
||||
}
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
char *utilAppNameWithNewExtensionGet(char *appName, char *extension);
|
||||
void utilDie(const char *why, ...);
|
||||
char *utilCreateString(char *format, ...);
|
||||
char *utilCreateStringVArgs(char *format, va_list args);
|
||||
|
||||
|
||||
#endif // UTIL_H
|
||||
|
|
Loading…
Add table
Reference in a new issue