Fixes for issues found by GCC analyzer.
This commit is contained in:
parent
d9889b2fbb
commit
36c6eeaf81
12 changed files with 270 additions and 100 deletions
54
analyze.sh
Executable file
54
analyze.sh
Executable file
|
|
@ -0,0 +1,54 @@
|
||||||
|
#!/bin/bash
|
||||||
|
#
|
||||||
|
# analyze.sh -- run the DJGPP build under gcc's -fanalyzer.
|
||||||
|
#
|
||||||
|
# Usage:
|
||||||
|
# ./analyze.sh # analyse the whole build (slow: 2-5x)
|
||||||
|
# ./analyze.sh 2>&1 | tee analyze.log
|
||||||
|
#
|
||||||
|
# How it works:
|
||||||
|
#
|
||||||
|
# The project Makefiles hardcode -Werror in CFLAGS. gcc evaluates
|
||||||
|
# diagnostic flags in order, so a trailing -Wno-error (appended
|
||||||
|
# AFTER CFLAGS at compile time) demotes analyzer findings back to
|
||||||
|
# warnings -- otherwise the first analyzer hit aborts the build.
|
||||||
|
#
|
||||||
|
# We do that by setting CC to a wrapper that execs the real compiler
|
||||||
|
# with -fanalyzer prepended and -Wno-error appended. make -k keeps
|
||||||
|
# building after individual failures so we see every hit in one run.
|
||||||
|
#
|
||||||
|
# Runs the existing top-level Makefile with an override CC; no
|
||||||
|
# Makefile edits required. Output goes to stderr; redirect with
|
||||||
|
# '2>&1 | tee analyze.log' to capture.
|
||||||
|
|
||||||
|
set -u
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
|
||||||
|
REAL_CC="$HOME/djgpp/djgpp/bin/i586-pc-msdosdjgpp-gcc"
|
||||||
|
|
||||||
|
if [ ! -x "$REAL_CC" ]; then
|
||||||
|
echo "analyze.sh: $REAL_CC not executable" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Build the wrapper in a temp dir that the spawned makes can see.
|
||||||
|
WRAP_DIR="$(mktemp -d)"
|
||||||
|
trap 'rm -rf "$WRAP_DIR"' EXIT
|
||||||
|
WRAP="$WRAP_DIR/analyze-cc"
|
||||||
|
|
||||||
|
cat > "$WRAP" <<WRAPEOF
|
||||||
|
#!/bin/bash
|
||||||
|
exec "$REAL_CC" -fanalyzer "\$@" -Wno-error
|
||||||
|
WRAPEOF
|
||||||
|
|
||||||
|
chmod +x "$WRAP"
|
||||||
|
|
||||||
|
echo "analyze.sh: running full build under gcc -fanalyzer..." >&2
|
||||||
|
echo "analyze.sh: this will be slow (2-5x normal build time)." >&2
|
||||||
|
|
||||||
|
# -k = keep going after errors so we collect every analyzer hit
|
||||||
|
# CC=... overrides the assignment in each submakefile
|
||||||
|
make -k CC="$WRAP" 2>&1
|
||||||
|
|
||||||
|
echo "analyze.sh: done. Grep for 'Wanalyzer' to see findings." >&2
|
||||||
|
|
@ -142,6 +142,12 @@ void widgetDestroyChildren(WidgetT *w);
|
||||||
// Allocation
|
// Allocation
|
||||||
WidgetT *widgetAlloc(WidgetT *parent, int32_t type);
|
WidgetT *widgetAlloc(WidgetT *parent, int32_t type);
|
||||||
|
|
||||||
|
// Undo a successful widgetAlloc when a subsequent data-struct
|
||||||
|
// allocation fails. Detaches from parent, removes from the poll
|
||||||
|
// list, frees the widget struct. Call only before w->data has
|
||||||
|
// been set; once data is attached, use wgtDestroy instead.
|
||||||
|
void widgetAllocRollback(WidgetT *w);
|
||||||
|
|
||||||
// Allocate a widget of the given type PLUS a data struct of dataSize
|
// Allocate a widget of the given type PLUS a data struct of dataSize
|
||||||
// bytes. The data struct must begin with a `const char *text` field
|
// bytes. The data struct must begin with a `const char *text` field
|
||||||
// (WCLASS_HAS_TEXT semantics); this field is set to strdup(text) and
|
// (WCLASS_HAS_TEXT semantics); this field is set to strdup(text) and
|
||||||
|
|
|
||||||
|
|
@ -257,6 +257,34 @@ WidgetT *widgetAlloc(WidgetT *parent, int32_t type) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Undo a successful widgetAlloc for a widget whose data-struct
|
||||||
|
// allocation subsequently failed. Detaches from parent, removes
|
||||||
|
// from the poll list, and frees the widget struct. Safe only
|
||||||
|
// before w->data has been set -- once data is attached, use
|
||||||
|
// wgtDestroy to run the widget's full teardown path.
|
||||||
|
void widgetAllocRollback(WidgetT *w) {
|
||||||
|
if (!w) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w->parent) {
|
||||||
|
widgetRemoveChild(w->parent, w);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (w->wclass && (w->wclass->flags & WCLASS_NEEDS_POLL)) {
|
||||||
|
for (int32_t i = 0; i < sPollWidgetCount; i++) {
|
||||||
|
if (sPollWidgets[i] == w) {
|
||||||
|
arrdel(sPollWidgets, i);
|
||||||
|
sPollWidgetCount = (int32_t)arrlen(sPollWidgets);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
free(w);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
WidgetT *widgetAllocWithText(WidgetT *parent, int32_t type, size_t dataSize, const char *text) {
|
WidgetT *widgetAllocWithText(WidgetT *parent, int32_t type, size_t dataSize, const char *text) {
|
||||||
WidgetT *w = widgetAlloc(parent, type);
|
WidgetT *w = widgetAlloc(parent, type);
|
||||||
|
|
||||||
|
|
@ -267,11 +295,9 @@ WidgetT *widgetAllocWithText(WidgetT *parent, int32_t type, size_t dataSize, con
|
||||||
void *data = calloc(1, dataSize);
|
void *data = calloc(1, dataSize);
|
||||||
|
|
||||||
if (!data) {
|
if (!data) {
|
||||||
// Widget itself is already in the tree; leave it rather than
|
|
||||||
// attempting a partial rollback (widget destroy is idempotent
|
|
||||||
// via the parent teardown).
|
|
||||||
dvxLog("Widget: failed to allocate %u-byte data for type %d", (unsigned)dataSize, type);
|
dvxLog("Widget: failed to allocate %u-byte data for type %d", (unsigned)dataSize, type);
|
||||||
return w;
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The data struct must begin with a `const char *text` field.
|
// The data struct must begin with a `const char *text` field.
|
||||||
|
|
|
||||||
|
|
@ -355,26 +355,32 @@ WidgetT *wgtCanvas(WidgetT *parent, int32_t w, int32_t h) {
|
||||||
|
|
||||||
WidgetT *wgt = widgetAlloc(parent, sTypeId);
|
WidgetT *wgt = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (wgt) {
|
if (!wgt) {
|
||||||
wgt->contentOffX = CANVAS_BORDER;
|
|
||||||
wgt->contentOffY = CANVAS_BORDER;
|
|
||||||
|
|
||||||
CanvasDataT *cd = (CanvasDataT *)calloc(1, sizeof(CanvasDataT));
|
|
||||||
|
|
||||||
cd->pixelData = data;
|
|
||||||
cd->canvasW = w;
|
|
||||||
cd->canvasH = h;
|
|
||||||
cd->canvasPitch = pitch;
|
|
||||||
cd->canvasBpp = bpp;
|
|
||||||
cd->penColor = packColor(d, 0, 0, 0);
|
|
||||||
cd->penSize = 1;
|
|
||||||
cd->lastX = -1;
|
|
||||||
cd->lastY = -1;
|
|
||||||
wgt->data = cd;
|
|
||||||
} else {
|
|
||||||
free(data);
|
free(data);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
wgt->contentOffX = CANVAS_BORDER;
|
||||||
|
wgt->contentOffY = CANVAS_BORDER;
|
||||||
|
|
||||||
|
CanvasDataT *cd = (CanvasDataT *)calloc(1, sizeof(CanvasDataT));
|
||||||
|
|
||||||
|
if (!cd) {
|
||||||
|
free(data);
|
||||||
|
widgetAllocRollback(wgt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
cd->pixelData = data;
|
||||||
|
cd->canvasW = w;
|
||||||
|
cd->canvasH = h;
|
||||||
|
cd->canvasPitch = pitch;
|
||||||
|
cd->canvasBpp = bpp;
|
||||||
|
cd->penColor = packColor(d, 0, 0, 0);
|
||||||
|
cd->penSize = 1;
|
||||||
|
cd->lastX = -1;
|
||||||
|
cd->lastY = -1;
|
||||||
|
wgt->data = cd;
|
||||||
return wgt;
|
return wgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,16 +81,23 @@ void widgetImagePaint(WidgetT *w, DisplayT *disp, const BlitOpsT *ops, const Bit
|
||||||
WidgetT *wgtImage(WidgetT *parent, uint8_t *pixelData, int32_t w, int32_t h, int32_t pitch) {
|
WidgetT *wgtImage(WidgetT *parent, uint8_t *pixelData, int32_t w, int32_t h, int32_t pitch) {
|
||||||
WidgetT *wgt = widgetAlloc(parent, sTypeId);
|
WidgetT *wgt = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (wgt) {
|
if (!wgt) {
|
||||||
ImageDataT *d = calloc(1, sizeof(ImageDataT));
|
return NULL;
|
||||||
d->pixelData = pixelData;
|
|
||||||
d->imgW = w;
|
|
||||||
d->imgH = h;
|
|
||||||
d->imgPitch = pitch;
|
|
||||||
d->pressed = false;
|
|
||||||
wgt->data = d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageDataT *d = calloc(1, sizeof(ImageDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(wgt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->pixelData = pixelData;
|
||||||
|
d->imgW = w;
|
||||||
|
d->imgH = h;
|
||||||
|
d->imgPitch = pitch;
|
||||||
|
d->pressed = false;
|
||||||
|
wgt->data = d;
|
||||||
return wgt;
|
return wgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -81,17 +81,25 @@ WidgetT *wgtImageButton(WidgetT *parent, uint8_t *pixelData, int32_t w, int32_t
|
||||||
|
|
||||||
WidgetT *wgt = widgetAlloc(parent, sTypeId);
|
WidgetT *wgt = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (wgt) {
|
if (!wgt) {
|
||||||
ImageButtonDataT *d = calloc(1, sizeof(ImageButtonDataT));
|
|
||||||
d->pixelData = pixelData;
|
|
||||||
d->imgW = w;
|
|
||||||
d->imgH = h;
|
|
||||||
d->imgPitch = pitch;
|
|
||||||
wgt->data = d;
|
|
||||||
} else {
|
|
||||||
free(pixelData);
|
free(pixelData);
|
||||||
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageButtonDataT *d = calloc(1, sizeof(ImageButtonDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
free(pixelData);
|
||||||
|
widgetAllocRollback(wgt);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->pixelData = pixelData;
|
||||||
|
d->imgW = w;
|
||||||
|
d->imgH = h;
|
||||||
|
d->imgPitch = pitch;
|
||||||
|
wgt->data = d;
|
||||||
|
|
||||||
return wgt;
|
return wgt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -68,14 +68,21 @@ void widgetProgressBarPaint(WidgetT *w, DisplayT *disp, const BlitOpsT *ops,
|
||||||
WidgetT *wgtProgressBar(WidgetT *parent) {
|
WidgetT *wgtProgressBar(WidgetT *parent) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTypeId);
|
WidgetT *w = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
ProgressBarDataT *d = calloc(1, sizeof(ProgressBarDataT));
|
return NULL;
|
||||||
d->value = 0;
|
|
||||||
d->maxValue = 100;
|
|
||||||
d->vertical = false;
|
|
||||||
w->data = d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProgressBarDataT *d = calloc(1, sizeof(ProgressBarDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->value = 0;
|
||||||
|
d->maxValue = 100;
|
||||||
|
d->vertical = false;
|
||||||
|
w->data = d;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -108,14 +115,21 @@ void wgtProgressBarSetValue(WidgetT *w, int32_t value) {
|
||||||
WidgetT *wgtProgressBarV(WidgetT *parent) {
|
WidgetT *wgtProgressBarV(WidgetT *parent) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTypeId);
|
WidgetT *w = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
ProgressBarDataT *d = calloc(1, sizeof(ProgressBarDataT));
|
return NULL;
|
||||||
d->value = 0;
|
|
||||||
d->maxValue = 100;
|
|
||||||
d->vertical = true;
|
|
||||||
w->data = d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ProgressBarDataT *d = calloc(1, sizeof(ProgressBarDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->value = 0;
|
||||||
|
d->maxValue = 100;
|
||||||
|
d->vertical = true;
|
||||||
|
w->data = d;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -65,20 +65,27 @@ void widgetSeparatorPaint(WidgetT *w, DisplayT *d, const BlitOpsT *ops,
|
||||||
WidgetT *wgtHSeparator(WidgetT *parent) {
|
WidgetT *wgtHSeparator(WidgetT *parent) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTypeId);
|
WidgetT *w = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
SeparatorDataT *d = calloc(1, sizeof(SeparatorDataT));
|
return NULL;
|
||||||
// Auto-orient to the parent: horizontal container -> vertical
|
|
||||||
// divider, vertical container -> horizontal divider. This
|
|
||||||
// lets a single "Line" basName work correctly in both
|
|
||||||
// toolbars and menus without requiring callers to pick
|
|
||||||
// between HSeparator and VSeparator by widget type.
|
|
||||||
if (parent && widgetIsHorizContainer(parent->type)) {
|
|
||||||
d->vertical = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
w->data = d;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SeparatorDataT *d = calloc(1, sizeof(SeparatorDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto-orient to the parent: horizontal container -> vertical
|
||||||
|
// divider, vertical container -> horizontal divider. This
|
||||||
|
// lets a single "Line" basName work correctly in both
|
||||||
|
// toolbars and menus without requiring callers to pick
|
||||||
|
// between HSeparator and VSeparator by widget type.
|
||||||
|
if (parent && widgetIsHorizContainer(parent->type)) {
|
||||||
|
d->vertical = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
w->data = d;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -126,12 +133,19 @@ void wgtRegister(void) {
|
||||||
WidgetT *wgtVSeparator(WidgetT *parent) {
|
WidgetT *wgtVSeparator(WidgetT *parent) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTypeId);
|
WidgetT *w = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
SeparatorDataT *d = calloc(1, sizeof(SeparatorDataT));
|
return NULL;
|
||||||
w->data = d;
|
|
||||||
d->vertical = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SeparatorDataT *d = calloc(1, sizeof(SeparatorDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
w->data = d;
|
||||||
|
d->vertical = true;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -132,15 +132,22 @@ void wgtRegister(void) {
|
||||||
WidgetT *wgtSlider(WidgetT *parent, int32_t minVal, int32_t maxVal) {
|
WidgetT *wgtSlider(WidgetT *parent, int32_t minVal, int32_t maxVal) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTypeId);
|
WidgetT *w = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
SliderDataT *d = (SliderDataT *)calloc(1, sizeof(SliderDataT));
|
return NULL;
|
||||||
d->value = minVal;
|
|
||||||
d->minValue = minVal;
|
|
||||||
d->maxValue = maxVal;
|
|
||||||
w->data = d;
|
|
||||||
w->weight = WGT_WEIGHT_FILL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SliderDataT *d = (SliderDataT *)calloc(1, sizeof(SliderDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->value = minVal;
|
||||||
|
d->minValue = minVal;
|
||||||
|
d->maxValue = maxVal;
|
||||||
|
w->data = d;
|
||||||
|
w->weight = WGT_WEIGHT_FILL;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -170,14 +170,21 @@ void wgtRegister(void) {
|
||||||
WidgetT *wgtSplitter(WidgetT *parent, bool vertical) {
|
WidgetT *wgtSplitter(WidgetT *parent, bool vertical) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTypeId);
|
WidgetT *w = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
SplitterDataT *d = (SplitterDataT *)calloc(1, sizeof(SplitterDataT));
|
return NULL;
|
||||||
d->vertical = vertical;
|
|
||||||
d->dividerPos = 0;
|
|
||||||
w->data = d;
|
|
||||||
w->weight = WGT_WEIGHT_FILL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SplitterDataT *d = (SplitterDataT *)calloc(1, sizeof(SplitterDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->vertical = vertical;
|
||||||
|
d->dividerPos = 0;
|
||||||
|
w->data = d;
|
||||||
|
w->weight = WGT_WEIGHT_FILL;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -193,14 +193,21 @@ static bool tabNeedScroll(const WidgetT *w, const BitmapFontT *font) {
|
||||||
WidgetT *wgtTabControl(WidgetT *parent) {
|
WidgetT *wgtTabControl(WidgetT *parent) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTabControlTypeId);
|
WidgetT *w = widgetAlloc(parent, sTabControlTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
TabControlDataT *d = calloc(1, sizeof(TabControlDataT));
|
return NULL;
|
||||||
d->activeTab = 0;
|
|
||||||
d->scrollOffset = 0;
|
|
||||||
w->data = d;
|
|
||||||
w->weight = WGT_WEIGHT_FILL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabControlDataT *d = calloc(1, sizeof(TabControlDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->activeTab = 0;
|
||||||
|
d->scrollOffset = 0;
|
||||||
|
w->data = d;
|
||||||
|
w->weight = WGT_WEIGHT_FILL;
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -225,13 +232,20 @@ void wgtTabControlSetActive(WidgetT *w, int32_t idx) {
|
||||||
WidgetT *wgtTabPage(WidgetT *parent, const char *title) {
|
WidgetT *wgtTabPage(WidgetT *parent, const char *title) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTabPageTypeId);
|
WidgetT *w = widgetAlloc(parent, sTabPageTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
TabPageDataT *d = calloc(1, sizeof(TabPageDataT));
|
return NULL;
|
||||||
d->title = strdup(title ? title : "");
|
|
||||||
w->data = d;
|
|
||||||
w->accelKey = accelParse(d->title);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TabPageDataT *d = calloc(1, sizeof(TabPageDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
d->title = strdup(title ? title : "");
|
||||||
|
w->data = d;
|
||||||
|
w->accelKey = accelParse(d->title);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -101,19 +101,26 @@ static void widgetTimerDestroy(WidgetT *w) {
|
||||||
WidgetT *wgtTimer(WidgetT *parent, int32_t intervalMs, bool repeat) {
|
WidgetT *wgtTimer(WidgetT *parent, int32_t intervalMs, bool repeat) {
|
||||||
WidgetT *w = widgetAlloc(parent, sTypeId);
|
WidgetT *w = widgetAlloc(parent, sTypeId);
|
||||||
|
|
||||||
if (w) {
|
if (!w) {
|
||||||
TimerDataT *d = calloc(1, sizeof(TimerDataT));
|
return NULL;
|
||||||
w->data = d;
|
|
||||||
w->visible = false;
|
|
||||||
d->intervalMs = intervalMs;
|
|
||||||
d->repeat = repeat;
|
|
||||||
// Match VB Timer default (Enabled=True on create). Callers can
|
|
||||||
// Stop() if they want it dormant.
|
|
||||||
d->running = true;
|
|
||||||
d->lastFire = clock();
|
|
||||||
timerAddToActiveList(w);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TimerDataT *d = calloc(1, sizeof(TimerDataT));
|
||||||
|
|
||||||
|
if (!d) {
|
||||||
|
widgetAllocRollback(w);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
w->data = d;
|
||||||
|
w->visible = false;
|
||||||
|
d->intervalMs = intervalMs;
|
||||||
|
d->repeat = repeat;
|
||||||
|
// Match VB Timer default (Enabled=True on create). Callers can
|
||||||
|
// Stop() if they want it dormant.
|
||||||
|
d->running = true;
|
||||||
|
d->lastFire = clock();
|
||||||
|
timerAddToActiveList(w);
|
||||||
return w;
|
return w;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue