Textboxes are working! This required a huge overhaul of painting, fixing clipping bound issues, adding timer support, and other things I have probably forgotten.
This commit is contained in:
parent
9494dee16d
commit
b17d78818f
13 changed files with 263 additions and 44 deletions
|
@ -1,4 +1,4 @@
|
||||||
#!/bin/bash
|
#!/bin/bash -e
|
||||||
|
|
||||||
#
|
#
|
||||||
# Kangaroo Punch MultiPlayer Game Server Mark II
|
# Kangaroo Punch MultiPlayer Game Server Mark II
|
||||||
|
@ -23,3 +23,21 @@ source /opt/cross/djgpp/setenv
|
||||||
make -f Makefile.djgpp
|
make -f Makefile.djgpp
|
||||||
rm bin/client
|
rm bin/client
|
||||||
cp data/* bin/.
|
cp data/* bin/.
|
||||||
|
|
||||||
|
:<<'SKIP'
|
||||||
|
[[ -f bin/CLIENT.LOG ]] && rm bin/CLIENT.LOG
|
||||||
|
|
||||||
|
cat <<-'BATCH' > bin/test.bat
|
||||||
|
@echo off
|
||||||
|
:wait
|
||||||
|
if not exist flag.dat goto wait
|
||||||
|
del flag.dat
|
||||||
|
client.exe 800 600 16
|
||||||
|
BATCH
|
||||||
|
|
||||||
|
touch bin/flag.dat
|
||||||
|
while [[ ! -f bin/CLIENT.LOG ]]; do
|
||||||
|
/bin/true
|
||||||
|
done
|
||||||
|
tail -f bin/CLIENT.LOG
|
||||||
|
SKIP
|
||||||
|
|
|
@ -46,8 +46,9 @@ enum MetaBitsE {
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
static int16_t _key = 0;
|
static int8_t _extended = 0;
|
||||||
static int16_t _meta = 0;
|
static int16_t _key = 0;
|
||||||
|
static int16_t _meta = 0;
|
||||||
|
|
||||||
|
|
||||||
uint8_t keyAlt(void) {
|
uint8_t keyAlt(void) {
|
||||||
|
@ -56,7 +57,7 @@ uint8_t keyAlt(void) {
|
||||||
|
|
||||||
|
|
||||||
uint8_t keyASCII(void) {
|
uint8_t keyASCII(void) {
|
||||||
return (uint8_t)(_key & 0x00FF);
|
return LOW_BYTE(_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -65,22 +66,43 @@ uint8_t keyControl(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t keyExtended(void) {
|
||||||
|
return _extended;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t keyHit(void) {
|
uint8_t keyHit(void) {
|
||||||
int16_t result = bioskey(KEYBOARD_CHECK_EXTENDED);
|
int16_t result = bioskey(KEYBOARD_CHECK_EXTENDED);
|
||||||
int16_t meta = bioskey(KEYBOARD_META_EXTENDED);
|
int16_t meta = bioskey(KEYBOARD_META_EXTENDED);
|
||||||
|
|
||||||
if (result > 0) {
|
if (result > 0) {
|
||||||
_key = bioskey(KEYBOARD_READ_EXTENDED);;
|
_key = bioskey(KEYBOARD_READ_EXTENDED);
|
||||||
_meta = meta;
|
_meta = meta;
|
||||||
|
|
||||||
|
// The value returned is a combination of the key's scan code in the high 8 bits
|
||||||
|
// and its ASCII code in the low 8 bits. For non-alphanumeric keys, such as the
|
||||||
|
// arrow keys, the low 8 bits are zeroed.
|
||||||
|
// Extended keys have the E0h prefix in the low 8 bits.
|
||||||
|
|
||||||
|
//logWrite("Raw key = %04X High = %02X Low = %02X\n", _key, HIGH_BYTE(_key), LOW_BYTE(_key));
|
||||||
|
|
||||||
|
if (LOW_BYTE(_key) == 0xE0) {
|
||||||
|
_extended = 1;
|
||||||
|
_key = HIGH_BYTE(_key);
|
||||||
|
} else {
|
||||||
|
_extended = 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_extended = 0;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t keyScanCode(void) {
|
uint8_t keyScanCode(void) {
|
||||||
return (uint8_t)((_key & 0xFF00) >> 8);
|
return HIGH_BYTE(_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -58,7 +58,7 @@ static char *_magicDebugNames[MAGIC_COUNT] = {
|
||||||
|
|
||||||
|
|
||||||
static void guiPaintBoundsGet(WidgetT *widget, RectT *pos);
|
static void guiPaintBoundsGet(WidgetT *widget, RectT *pos);
|
||||||
static void guiProcessKeyboardChildren(WidgetT *widget, uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
static void guiProcessKeyboardChildren(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
||||||
static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse);
|
static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse);
|
||||||
|
|
||||||
|
|
||||||
|
@ -255,17 +255,24 @@ WidgetT *guiFocusGet(void) {
|
||||||
|
|
||||||
|
|
||||||
void guiFocusSet(WidgetT *widget) {
|
void guiFocusSet(WidgetT *widget) {
|
||||||
|
// Is this widget on the active window?
|
||||||
|
if (widget->window) {
|
||||||
|
if (!GUI_GET_FLAG(W(widget->window), WIDGET_FLAG_ACTIVE)) {
|
||||||
|
// Cancel focus change.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
// Did the focus change?
|
// Did the focus change?
|
||||||
if (widget != _guiFocused) {
|
if (widget != _guiFocused) {
|
||||||
// Remove focus from current control.
|
// Remove focus from current control.
|
||||||
if (_guiFocused) {
|
if (_guiFocused) {
|
||||||
if (_guiFocused->focusMethod) _guiFocused->focusMethod(widget, 0);
|
if (_guiFocused->focusMethod) _guiFocused->focusMethod(_guiFocused, 0);
|
||||||
}
|
}
|
||||||
// Change focus.
|
// Change focus.
|
||||||
_guiFocused = widget;
|
_guiFocused = widget;
|
||||||
// Tell new control it has focus.
|
// Tell new control it has focus.
|
||||||
if (_guiFocused) {
|
if (_guiFocused) {
|
||||||
if (_guiFocused->focusMethod) _guiFocused->focusMethod(widget, 1);
|
if (_guiFocused->focusMethod) _guiFocused->focusMethod(_guiFocused, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -406,33 +413,33 @@ static uint8_t guiProcessMouseChildren(WidgetT *widget, MouseT *mouse) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void guiProcessKeyboard(uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) {
|
void guiProcessKeyboard(uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) {
|
||||||
// Does the focused widget want events? Check for global keyboard so it doesn't get double events.
|
// Does the focused widget want events? Check for global keyboard so it doesn't get double events.
|
||||||
if (_guiFocused) {
|
if (_guiFocused) {
|
||||||
if (_guiFocused->keyboardEventMethod && !GUI_GET_FLAG(_guiFocused, WIDGET_FLAG_ALWAYS_RECEIVE_KEYBOARD_EVENTS)) {
|
if (_guiFocused->keyboardEventMethod && !GUI_GET_FLAG(_guiFocused, WIDGET_FLAG_ALWAYS_RECEIVE_KEYBOARD_EVENTS)) {
|
||||||
_guiFocused->keyboardEventMethod(_guiFocused, ascii, scancode, shift, control, alt);
|
_guiFocused->keyboardEventMethod(_guiFocused, ascii, extended, scancode, shift, control, alt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check everyone for global keyboard handling.
|
// Check everyone for global keyboard handling.
|
||||||
guiProcessKeyboardChildren((WidgetT *)_guiDesktop, ascii, scancode, shift, control, alt);
|
guiProcessKeyboardChildren((WidgetT *)_guiDesktop, ascii, extended, scancode, shift, control, alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void guiProcessKeyboardChildren(WidgetT *widget, uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) {
|
static void guiProcessKeyboardChildren(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 len;
|
||||||
size_t x;
|
size_t x;
|
||||||
|
|
||||||
// Process children of this widget.
|
// Process children of this widget.
|
||||||
len = arrlenu(widget->children);
|
len = arrlenu(widget->children);
|
||||||
for (x=0; x<len; x++) {
|
for (x=0; x<len; x++) {
|
||||||
guiProcessKeyboardChildren(widget->children[x], ascii, scancode, shift, control, alt);
|
guiProcessKeyboardChildren(widget->children[x], ascii, extended, scancode, shift, control, alt);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Does this widget want events? Check for global keyboard so it doesn't get double events.
|
// Does this widget want events? Check for global keyboard so it doesn't get double events.
|
||||||
if (widget) {
|
if (widget) {
|
||||||
if (widget->keyboardEventMethod && GUI_GET_FLAG(widget, WIDGET_FLAG_ALWAYS_RECEIVE_KEYBOARD_EVENTS)) {
|
if (widget->keyboardEventMethod && GUI_GET_FLAG(widget, WIDGET_FLAG_ALWAYS_RECEIVE_KEYBOARD_EVENTS)) {
|
||||||
widget->keyboardEventMethod(widget, ascii, scancode, shift, control, alt);
|
widget->keyboardEventMethod(widget, ascii, extended, scancode, shift, control, alt);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -144,7 +144,7 @@ void guiFocusSet(WidgetT *widget);
|
||||||
void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y);
|
void guiMousePositionOnWidgetGet(WidgetT *widget, MouseT *mouse, uint16_t *x, uint16_t *y);
|
||||||
void guiPaint(WidgetT *widget);
|
void guiPaint(WidgetT *widget);
|
||||||
void guiProcessMouse(MouseT *mouse);
|
void guiProcessMouse(MouseT *mouse);
|
||||||
void guiProcessKeyboard(uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
void guiProcessKeyboard(uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
||||||
WidgetT *guiRootGet(void);
|
WidgetT *guiRootGet(void);
|
||||||
void guiSetWidgetAndChildrenDirty(WidgetT *widget);
|
void guiSetWidgetAndChildrenDirty(WidgetT *widget);
|
||||||
DesktopT *guiStartup(void);
|
DesktopT *guiStartup(void);
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
uint8_t keyAlt(void);
|
uint8_t keyAlt(void);
|
||||||
uint8_t keyASCII(void);
|
uint8_t keyASCII(void);
|
||||||
uint8_t keyControl(void);
|
uint8_t keyControl(void);
|
||||||
|
uint8_t keyExtended(void);
|
||||||
uint8_t keyHit(void);
|
uint8_t keyHit(void);
|
||||||
uint8_t keyScanCode(void);
|
uint8_t keyScanCode(void);
|
||||||
uint8_t keyShift(void);
|
uint8_t keyShift(void);
|
||||||
|
|
|
@ -55,6 +55,8 @@ long biostime(int cmd, long newtime);
|
||||||
|
|
||||||
|
|
||||||
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
|
#define DIVISIBLE_BY_EIGHT(x) ((((x) >> 3) << 3) == (x))
|
||||||
|
#define HIGH_BYTE(b) ((uint8_t)(((b) & 0xFF00) >> 8))
|
||||||
|
#define LOW_BYTE(b) ((uint8_t)((b) & 0x00FF))
|
||||||
|
|
||||||
|
|
||||||
#endif // OS_H
|
#endif // OS_H
|
||||||
|
|
|
@ -19,11 +19,12 @@
|
||||||
|
|
||||||
|
|
||||||
#include "textbox.h"
|
#include "textbox.h"
|
||||||
|
#include "timer.h"
|
||||||
|
|
||||||
|
|
||||||
static void textboxFocusEvent(WidgetT *widget, uint8_t focused);
|
static void textboxFocusEvent(WidgetT *widget, uint8_t focused);
|
||||||
static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
||||||
static void textboxPaint(WidgetT *widget, RectT pos);
|
static void textboxPaint(WidgetT *widget, RectT pos);
|
||||||
|
|
||||||
|
|
||||||
|
@ -38,7 +39,10 @@ void textboxDel(WidgetT **widget) {
|
||||||
|
|
||||||
|
|
||||||
static void textboxFocusEvent(WidgetT *widget, uint8_t focused) {
|
static void textboxFocusEvent(WidgetT *widget, uint8_t focused) {
|
||||||
|
// Make sure cursor disappears when we lose focus.
|
||||||
|
if (!focused) {
|
||||||
|
GUI_SET_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -59,6 +63,7 @@ WidgetT *textboxInit(WidgetT *widget, char *title) {
|
||||||
t->maxLength = 256;
|
t->maxLength = 256;
|
||||||
t->value = (char *)malloc(t->maxLength);
|
t->value = (char *)malloc(t->maxLength);
|
||||||
t->caret = 0;
|
t->caret = 0;
|
||||||
|
t->offset = 0;
|
||||||
|
|
||||||
if (!t->value) return NULL;
|
if (!t->value) return NULL;
|
||||||
t->value[0] = 0;
|
t->value[0] = 0;
|
||||||
|
@ -70,8 +75,115 @@ WidgetT *textboxInit(WidgetT *widget, char *title) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) {
|
static void textboxKeyboardEvent(WidgetT *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt) {
|
||||||
|
|
||||||
|
TextboxT *t = (TextboxT *)widget;
|
||||||
|
uint16_t x;
|
||||||
|
|
||||||
|
(void)scancode;
|
||||||
|
(void)shift;
|
||||||
|
(void)control;
|
||||||
|
(void)alt;
|
||||||
|
|
||||||
|
if (extended) {
|
||||||
|
|
||||||
|
switch (ascii) {
|
||||||
|
case 75: // LEFT
|
||||||
|
// Can we move left in the value?
|
||||||
|
if (t->caret + t->offset > 0) {
|
||||||
|
// Is the caret on the left edge of the box?
|
||||||
|
if (t->caret == 0) {
|
||||||
|
// Can we move the string offset?
|
||||||
|
if (t->offset > 0) {
|
||||||
|
t->offset--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Move the caret left.
|
||||||
|
t->caret--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 77: // RIGHT
|
||||||
|
// Can we move right in the value?
|
||||||
|
if (t->caret + t->offset < strlen(t->value)) {
|
||||||
|
// Is the caret on the right edge of the box?
|
||||||
|
if (t->caret == t->visible - 1) {
|
||||||
|
// Can we move the string offset?
|
||||||
|
if (t->offset < strlen(t->value)) {
|
||||||
|
t->offset++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Move the caret right.
|
||||||
|
t->caret++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 83: // DELETE
|
||||||
|
// Is there more data to the right in the value?
|
||||||
|
if (t->caret + t->offset < strlen(t->value)) {
|
||||||
|
// Delete character under caret.
|
||||||
|
for (x = t->caret + t->offset; x<strlen(t->value); x++) {
|
||||||
|
t->value[x] = t->value[x+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
} // switch
|
||||||
|
|
||||||
|
} else { // extended
|
||||||
|
|
||||||
|
switch (ascii) {
|
||||||
|
case 8: // BACKSPACE
|
||||||
|
// Can we delete left in the value?
|
||||||
|
if (t->caret + t->offset > 0) {
|
||||||
|
// Is the caret on the left edge of the box?
|
||||||
|
if (t->caret == 0) {
|
||||||
|
// Can we move the string offset?
|
||||||
|
if (t->offset > 0) {
|
||||||
|
t->offset--;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Move the caret left.
|
||||||
|
t->caret--;
|
||||||
|
}
|
||||||
|
// Delete the character to the left of the caret.
|
||||||
|
for (x = t->caret + t->offset; x<strlen(t->value); x++) {
|
||||||
|
t->value[x] = t->value[x+1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default: // Other keys
|
||||||
|
if (ascii >= 32 && ascii <= 126) {
|
||||||
|
// Insert character, if room.
|
||||||
|
if (strlen(t->value) < t->maxLength - 1) {
|
||||||
|
// Move existing characters over, if needed.
|
||||||
|
if (t->caret + t->offset < strlen(t->value)) {
|
||||||
|
for (x=strlen(t->value) + 1; x>t->caret + t->offset; x--) {
|
||||||
|
t->value[x] = t->value[x-1];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Place typed character at caret.
|
||||||
|
t->value[t->caret + t->offset] = ascii;
|
||||||
|
// Is the caret on the right edge of the box?
|
||||||
|
if (t->caret == t->visible - 1) {
|
||||||
|
// Can we move the string offset?
|
||||||
|
if (t->offset < strlen(t->value)) {
|
||||||
|
t->offset++;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Move the caret right.
|
||||||
|
t->caret++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
} // switch
|
||||||
|
|
||||||
|
} // extended
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -82,7 +194,10 @@ static void textboxMouseEvent(WidgetT *widget, MouseT *mouse, uint16_t x, uint16
|
||||||
(void)y;
|
(void)y;
|
||||||
(void)mouse;
|
(void)mouse;
|
||||||
|
|
||||||
//***TODO*** Allow dragging text cursor with mouse.
|
//***TODO*** Allow dragging/positioning text cursor with mouse.
|
||||||
|
if (event == MOUSE_EVENT_LEFT_HOLD) {
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,8 +225,12 @@ static void textboxPaint(WidgetT *widget, RectT pos) {
|
||||||
char *draw = NULL;
|
char *draw = NULL;
|
||||||
uint16_t labelWidth;
|
uint16_t labelWidth;
|
||||||
uint16_t valueWidth;
|
uint16_t valueWidth;
|
||||||
|
uint16_t caretPos;
|
||||||
|
uint16_t textX;
|
||||||
|
uint16_t textY;
|
||||||
|
char cursor[2] = { 0xb1, 0 };
|
||||||
|
|
||||||
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY)) {
|
if (GUI_GET_FLAG(widget, WIDGET_FLAG_DIRTY) || guiFocusGet() == widget) {
|
||||||
labelWidth = (strlen(t->title) * fontWidthGet(_guiFont)) + _guiMetric[METRIC_TEXTBOX_PADDING];
|
labelWidth = (strlen(t->title) * fontWidthGet(_guiFont)) + _guiMetric[METRIC_TEXTBOX_PADDING];
|
||||||
valueWidth = (t->visible * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING] * 2);
|
valueWidth = (t->visible * fontWidthGet(_guiFont)) + (_guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING] * 2);
|
||||||
|
|
||||||
|
@ -125,12 +244,23 @@ static void textboxPaint(WidgetT *widget, RectT pos) {
|
||||||
// Draw background.
|
// Draw background.
|
||||||
guiDrawRectangleFilled(pos.x + labelWidth + 2, pos.y + 2, pos.x + labelWidth + valueWidth, pos.y + pos.h - 2, _guiColor[COLOR_TEXTBOX_BACKGROUND]);
|
guiDrawRectangleFilled(pos.x + labelWidth + 2, pos.y + 2, pos.x + labelWidth + valueWidth, pos.y + pos.h - 2, _guiColor[COLOR_TEXTBOX_BACKGROUND]);
|
||||||
|
|
||||||
// Draw value. ***TODO*** This needs much more!
|
// Where's the text display start?
|
||||||
draw = strdup(t->value);
|
textX = pos.x + labelWidth + 2 + _guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING];
|
||||||
|
textY = pos.y + 2 + _guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING];
|
||||||
|
|
||||||
|
// Draw value. ***TODO*** This needs much more! Do it without strdup?
|
||||||
|
draw = strdup(&t->value[t->offset]);
|
||||||
if (strlen(t->value) > t->visible) draw[t->visible] = 0;
|
if (strlen(t->value) > t->visible) draw[t->visible] = 0;
|
||||||
fontRender(_guiFont, draw, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], pos.x + labelWidth + 2 + _guiMetric[METRIC_TEXTBOX_HORIZONTAL_PADDING], pos.y + 2 + _guiMetric[METRIC_TEXTBOX_VERTICAL_PADDING]);
|
fontRender(_guiFont, draw, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], textX, textY);
|
||||||
free(draw);
|
free(draw);
|
||||||
|
|
||||||
|
// Draw cursor.
|
||||||
|
if (guiFocusGet() == widget && timerQuarterSecondOn) {
|
||||||
|
caretPos = textX + fontWidthGet(_guiFont) * t->caret;
|
||||||
|
//logWrite("textX %d textY %d caretPos %d\n", textX, textY, caretPos);
|
||||||
|
fontRender(_guiFont, cursor, _guiColor[COLOR_TEXTBOX_TEXT], _guiColor[COLOR_TEXTBOX_BACKGROUND], caretPos, textY);
|
||||||
|
}
|
||||||
|
|
||||||
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
GUI_CLEAR_FLAG(widget, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -140,6 +270,14 @@ void textboxSetValue(TextboxT *textbox, char *value) {
|
||||||
// Copy it & truncate if needed.
|
// Copy it & truncate if needed.
|
||||||
strncpy(textbox->value, value, textbox->maxLength - 1);
|
strncpy(textbox->value, value, textbox->maxLength - 1);
|
||||||
|
|
||||||
|
// Is this longer than the area we have to display it in?
|
||||||
|
if (strlen(textbox->value) > textbox->visible - 1) {
|
||||||
|
textbox->offset = strlen(textbox->value) - (textbox->visible - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set caret position.
|
||||||
|
textbox->caret = strlen(&textbox->value[textbox->offset]);
|
||||||
|
|
||||||
GUI_SET_FLAG((WidgetT *)textbox, WIDGET_FLAG_DIRTY);
|
GUI_SET_FLAG((WidgetT *)textbox, WIDGET_FLAG_DIRTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -34,7 +34,6 @@ typedef struct TextboxS {
|
||||||
uint16_t caret; // Cursor position in control (caret + offset = cursor positition in value)
|
uint16_t caret; // Cursor position in control (caret + offset = cursor positition in value)
|
||||||
uint16_t offset; // First character position to display in control
|
uint16_t offset; // First character position to display in control
|
||||||
uint8_t visible; // How many characters are visible in control
|
uint8_t visible; // How many characters are visible in control
|
||||||
uint8_t blink;
|
|
||||||
} TextboxT;
|
} TextboxT;
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -26,12 +26,14 @@
|
||||||
#define TICKS_PER_DAY (SECONDS_IN_DAY * TICKS_PER_SECOND)
|
#define TICKS_PER_DAY (SECONDS_IN_DAY * TICKS_PER_SECOND)
|
||||||
|
|
||||||
|
|
||||||
uint8_t timerHalfSecondOn = 0;
|
uint8_t timerQuarterSecondOn = 0;
|
||||||
uint8_t timerSecondOn = 0;
|
uint8_t timerHalfSecondOn = 0;
|
||||||
|
uint8_t timerSecondOn = 0;
|
||||||
|
|
||||||
|
|
||||||
static long _timerLast = 0;
|
static long _timerLast = 0;
|
||||||
static uint8_t _timerSecond = 2;
|
static uint8_t _timerHalfSecond = 2;
|
||||||
|
static uint8_t _timerSecond = 2;
|
||||||
|
|
||||||
|
|
||||||
void timerShutdown(void) {
|
void timerShutdown(void) {
|
||||||
|
@ -58,16 +60,25 @@ void timerUpdate(void) {
|
||||||
delta = (now + TICKS_PER_DAY) - _timerLast;
|
delta = (now + TICKS_PER_DAY) - _timerLast;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (delta > TICKS_PER_SECOND * 0.5) {
|
// Everything ticks off the quarter second.
|
||||||
|
if (delta > TICKS_PER_SECOND * 0.25) {
|
||||||
_timerLast = now;
|
_timerLast = now;
|
||||||
|
|
||||||
// Half Second timer
|
// Quarter Second timer.
|
||||||
timerHalfSecondOn = !timerHalfSecondOn;
|
timerQuarterSecondOn = !timerQuarterSecondOn;
|
||||||
|
|
||||||
// Second timer
|
// Half Second timer.
|
||||||
if (--_timerSecond == 0) {
|
if (--_timerHalfSecond == 0) {
|
||||||
_timerSecond = 2;
|
_timerHalfSecond = 2;
|
||||||
timerSecondOn = !timerSecondOn;
|
timerHalfSecondOn = !timerHalfSecondOn;
|
||||||
}
|
|
||||||
}
|
// Second timer
|
||||||
|
if (--_timerSecond == 0) {
|
||||||
|
_timerSecond = 2;
|
||||||
|
timerSecondOn = !timerSecondOn;
|
||||||
|
} // Second.
|
||||||
|
|
||||||
|
} // Half Second.
|
||||||
|
|
||||||
|
} // Quarter Second.
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,7 @@
|
||||||
#include "os.h"
|
#include "os.h"
|
||||||
|
|
||||||
|
|
||||||
|
extern uint8_t timerQuarterSecondOn;
|
||||||
extern uint8_t timerHalfSecondOn;
|
extern uint8_t timerHalfSecondOn;
|
||||||
extern uint8_t timerSecondOn;
|
extern uint8_t timerSecondOn;
|
||||||
|
|
||||||
|
|
|
@ -40,7 +40,7 @@ typedef struct WindowS WindowT;
|
||||||
typedef void (*widgetCallback)(struct WidgetS *widget);
|
typedef void (*widgetCallback)(struct WidgetS *widget);
|
||||||
typedef void (*widgetDelMethod)(struct WidgetS **widget);
|
typedef void (*widgetDelMethod)(struct WidgetS **widget);
|
||||||
typedef void (*widgetFocusMethod)(struct WidgetS *widget, uint8_t focused);
|
typedef void (*widgetFocusMethod)(struct WidgetS *widget, uint8_t focused);
|
||||||
typedef void (*widgetKeyboardEventMethod)(struct WidgetS *widget, uint8_t ascii, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
typedef void (*widgetKeyboardEventMethod)(struct WidgetS *widget, uint8_t ascii, uint8_t extended, uint8_t scancode, uint8_t shift, uint8_t control, uint8_t alt);
|
||||||
typedef void (*widgetPaintMethod)(struct WidgetS *widget, RectT pos);
|
typedef void (*widgetPaintMethod)(struct WidgetS *widget, RectT pos);
|
||||||
typedef void (*widgetMouseEventMethod)(struct WidgetS *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
typedef void (*widgetMouseEventMethod)(struct WidgetS *widget, MouseT *mouse, uint16_t x, uint16_t y, uint8_t event);
|
||||||
|
|
||||||
|
|
|
@ -46,6 +46,7 @@ static uint8_t _control = 0;
|
||||||
static uint8_t _shift = 0;
|
static uint8_t _shift = 0;
|
||||||
static uint8_t _ASCII = 0;
|
static uint8_t _ASCII = 0;
|
||||||
static uint8_t _scanCode = 0;
|
static uint8_t _scanCode = 0;
|
||||||
|
static uint8_t _extended = 0;
|
||||||
static uint8_t _ASCIIKeep = 0;
|
static uint8_t _ASCIIKeep = 0;
|
||||||
static uint8_t _scanCodeKeep = 0;
|
static uint8_t _scanCodeKeep = 0;
|
||||||
static uint8_t _keyPressed = 0;
|
static uint8_t _keyPressed = 0;
|
||||||
|
@ -84,6 +85,11 @@ uint8_t keyControl(void) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
uint8_t keyExtended(void) {
|
||||||
|
return _extended;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
uint8_t keyHit(void) {
|
uint8_t keyHit(void) {
|
||||||
uint8_t result = 0;
|
uint8_t result = 0;
|
||||||
|
|
||||||
|
@ -91,10 +97,19 @@ uint8_t keyHit(void) {
|
||||||
|
|
||||||
result = _keyPressed;
|
result = _keyPressed;
|
||||||
if (result) {
|
if (result) {
|
||||||
if (_scanCode == 41) _ASCII = 27; // Fix ESC mapping.
|
// Default mapping.
|
||||||
|
_extended = 0;
|
||||||
_ASCIIKeep = _ASCII;
|
_ASCIIKeep = _ASCII;
|
||||||
_scanCodeKeep = _scanCode;
|
_scanCodeKeep = _scanCode;
|
||||||
_keyPressed = 0;
|
_keyPressed = 0;
|
||||||
|
// Fix mappings to match DOS bioskey() call.
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_ESCAPE) _ASCIIKeep = 27;
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_BACKSPACE) _ASCIIKeep = 8;
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_DELETE) { _extended = 1; _ASCIIKeep = 83; }
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_LEFT) { _extended = 1; _ASCIIKeep = 75; }
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_RIGHT) { _extended = 1; _ASCIIKeep = 77; }
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_UP) { _extended = 1; _ASCIIKeep = 72; }
|
||||||
|
if (_scanCodeKeep == SDL_SCANCODE_DOWN) { _extended = 1; _ASCIIKeep = 80; }
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
* - More widget states: Ghosted, hidden
|
* - More widget states: Ghosted, hidden
|
||||||
* - Move setup math for paint events inside the dirty check
|
* - Move setup math for paint events inside the dirty check
|
||||||
* - Methods that can change the width of a widget (such as setTitle) need to repaint the parent window as well
|
* - Methods that can change the width of a widget (such as setTitle) need to repaint the parent window as well
|
||||||
|
* - Focus events are firing for controls not in top level window
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
@ -97,8 +98,8 @@ void mainLoop(void *data) {
|
||||||
mouse = mouseRead();
|
mouse = mouseRead();
|
||||||
if (keyHit()) {
|
if (keyHit()) {
|
||||||
key = keyASCII();
|
key = keyASCII();
|
||||||
guiProcessKeyboard(keyASCII(), keyScanCode(), keyShift(), keyControl(), keyAlt());
|
guiProcessKeyboard(keyASCII(), keyExtended(), keyScanCode(), keyShift(), keyControl(), keyAlt());
|
||||||
//logWrite("Key '%d' Control '%d'\n", key, keyControl());
|
//logWrite("Key '%d' Extended '%d' Scancode '%d' Shift '%d' Control '%d' Alt '%d'\n", key, keyExtended(), keyScanCode(), keyShift(), keyControl(), keyAlt());
|
||||||
} else {
|
} else {
|
||||||
key = 0;
|
key = 0;
|
||||||
}
|
}
|
||||||
|
@ -112,7 +113,7 @@ void mainLoop(void *data) {
|
||||||
if (debugState > 2) debugState = 0;
|
if (debugState > 2) debugState = 0;
|
||||||
}
|
}
|
||||||
if (debugState > 0) drawWidgetDebug(guiRootGet(), debugState - 1);
|
if (debugState > 0) drawWidgetDebug(guiRootGet(), debugState - 1);
|
||||||
if (timerHalfSecondOn) guiDrawRectangle(0, 0, vbeSurfaceWidthGet() - 1, vbeSurfaceHeightGet() - 1, vbeMakeColor(255, 255, 255));
|
//if (timerHalfSecondOn) guiDrawRectangle(0, 0, vbeSurfaceWidthGet() - 1, vbeSurfaceHeightGet() - 1, vbeMakeColor(255, 255, 255));
|
||||||
|
|
||||||
vbeWaitVBlank();
|
vbeWaitVBlank();
|
||||||
vbePresent();
|
vbePresent();
|
||||||
|
@ -139,6 +140,7 @@ void test(void *data) {
|
||||||
PictureT *p1 = NULL;
|
PictureT *p1 = NULL;
|
||||||
FrameT *f1 = NULL;
|
FrameT *f1 = NULL;
|
||||||
TextboxT *t1 = NULL;
|
TextboxT *t1 = NULL;
|
||||||
|
TextboxT *t2 = NULL;
|
||||||
|
|
||||||
(void)data;
|
(void)data;
|
||||||
|
|
||||||
|
@ -170,8 +172,11 @@ void test(void *data) {
|
||||||
radioSetSelected(r1a);
|
radioSetSelected(r1a);
|
||||||
radioSetSelected(r2b);
|
radioSetSelected(r2b);
|
||||||
t1 = textboxNew(10, 60, 265, "Test Textbox");
|
t1 = textboxNew(10, 60, 265, "Test Textbox");
|
||||||
textboxSetValue(t1, "Text to edit!");
|
textboxSetValue(t1, "Really long text string to edit!");
|
||||||
guiAttach(W(w2), W(t1));
|
guiAttach(W(w2), W(t1));
|
||||||
|
t2 = textboxNew(10, 85, 265, "Test Textbox");
|
||||||
|
textboxSetValue(t2, "Short string.");
|
||||||
|
guiAttach(W(w2), W(t2));
|
||||||
|
|
||||||
// Window 3
|
// Window 3
|
||||||
f1 = frameNew(10, 5, 175, 125, "Test Frame");
|
f1 = frameNew(10, 5, 175, 125, "Test Frame");
|
||||||
|
|
Loading…
Add table
Reference in a new issue