|
|
@ -26,54 +26,54 @@ |
|
|
|
#define gh2obj ((GTexteditObject *)gh) |
|
|
|
#define gw2obj ((GTexteditObject *)gw) |
|
|
|
|
|
|
|
static void TextEditRemoveChar(GWidgetObject* gw) { |
|
|
|
static void TextEditRemoveChar(GHandle gh) { |
|
|
|
char *p; |
|
|
|
const char *q; |
|
|
|
unsigned sz; |
|
|
|
unsigned pos; |
|
|
|
|
|
|
|
sz = strlen(gw->text); |
|
|
|
pos = gw2obj->cursorPos; |
|
|
|
q = gw->text+pos; |
|
|
|
sz = strlen(gh2obj->w.text); |
|
|
|
pos = gh2obj->cursorPos; |
|
|
|
q = gh2obj->w.text+pos; |
|
|
|
|
|
|
|
if (!(gw->g.flags & GWIN_FLG_ALLOCTXT)) { |
|
|
|
if (!(gh->flags & GWIN_FLG_ALLOCTXT)) { |
|
|
|
// Allocate and then copy
|
|
|
|
if (!(p = gfxAlloc(sz))) |
|
|
|
return; |
|
|
|
if (pos) |
|
|
|
memcpy(p, gw->text, pos); |
|
|
|
memcpy(p, gh2obj->w.text, pos); |
|
|
|
memcpy(p+pos, q+1, sz-pos); |
|
|
|
gw->g.flags |= GWIN_FLG_ALLOCTXT; |
|
|
|
gh->flags |= GWIN_FLG_ALLOCTXT; |
|
|
|
} else { |
|
|
|
// Copy and then reallocate
|
|
|
|
memcpy((char *)q, q+1, sz-pos); |
|
|
|
if (!(p = gfxRealloc((char *)gw->text, sz+1, sz))) // This should never fail as we are making it smaller
|
|
|
|
if (!(p = gfxRealloc((char *)gh2obj->w.text, sz+1, sz))) // This should never fail as we are making it smaller
|
|
|
|
return; |
|
|
|
} |
|
|
|
gw->text = p; |
|
|
|
gh2obj->w.text = p; |
|
|
|
} |
|
|
|
|
|
|
|
static bool_t TextEditAddChars(GWidgetObject* gw, unsigned cnt) { |
|
|
|
static bool_t TextEditAddChars(GHandle gh, unsigned cnt) { |
|
|
|
char *p; |
|
|
|
const char *q; |
|
|
|
unsigned sz; |
|
|
|
unsigned pos; |
|
|
|
|
|
|
|
// Get the size of the text buffer
|
|
|
|
sz = strlen(gw->text)+1; |
|
|
|
pos = gw2obj->cursorPos; |
|
|
|
sz = strlen(gh2obj->w.text)+1; |
|
|
|
pos = gh2obj->cursorPos; |
|
|
|
|
|
|
|
if (!(gw->g.flags & GWIN_FLG_ALLOCTXT)) { |
|
|
|
if (!(gh->flags & GWIN_FLG_ALLOCTXT)) { |
|
|
|
if (!(p = gfxAlloc(sz+cnt))) |
|
|
|
return FALSE; |
|
|
|
memcpy(p, gw->text, pos); |
|
|
|
memcpy(p+pos+cnt, gw->text+pos, sz-pos); |
|
|
|
gw->g.flags |= GWIN_FLG_ALLOCTXT; |
|
|
|
gw->text = p; |
|
|
|
memcpy(p, gh2obj->w.text, pos); |
|
|
|
memcpy(p+pos+cnt, gh2obj->w.text+pos, sz-pos); |
|
|
|
gh->flags |= GWIN_FLG_ALLOCTXT; |
|
|
|
gh2obj->w.text = p; |
|
|
|
} else { |
|
|
|
if (!(p = gfxRealloc((char *)gw->text, sz, sz+cnt))) |
|
|
|
if (!(p = gfxRealloc((char *)gh2obj->w.text, sz, sz+cnt))) |
|
|
|
return FALSE; |
|
|
|
gw->text = p; |
|
|
|
gh2obj->w.text = p; |
|
|
|
q = p+pos; |
|
|
|
p += sz; |
|
|
|
while(--p >= q) |
|
|
@ -117,76 +117,13 @@ static void TextEditMouseDown(GWidgetObject* gw, coord_t x, coord_t y) { |
|
|
|
|
|
|
|
// Is it a special key?
|
|
|
|
if (pke->keystate & GKEYSTATE_SPECIAL) { |
|
|
|
|
|
|
|
// Arrow keys to move the cursor
|
|
|
|
switch ((uint8_t)pke->c[0]) { |
|
|
|
case GKEY_LEFT: |
|
|
|
if (!gw2obj->cursorPos) |
|
|
|
return; |
|
|
|
gw2obj->cursorPos--; |
|
|
|
break; |
|
|
|
case GKEY_RIGHT: |
|
|
|
if (!gw->text[gw2obj->cursorPos]) |
|
|
|
return; |
|
|
|
gw2obj->cursorPos++; |
|
|
|
break; |
|
|
|
case GKEY_HOME: |
|
|
|
if (!gw2obj->cursorPos) |
|
|
|
return; |
|
|
|
gw2obj->cursorPos = 0; |
|
|
|
break; |
|
|
|
case GKEY_END: |
|
|
|
if (!gw->text[gw2obj->cursorPos]) |
|
|
|
return; |
|
|
|
gw2obj->cursorPos = strlen(gw->text); |
|
|
|
break; |
|
|
|
default: |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
} else { |
|
|
|
gwinTextEditSendSpecialKey(&gw->g, (uint8_t)pke->c[0]); |
|
|
|
return; |
|
|
|
|
|
|
|
// Normal key press
|
|
|
|
switch((uint8_t)pke->c[0]) { |
|
|
|
case GKEY_BACKSPACE: |
|
|
|
// Backspace
|
|
|
|
if (!gw2obj->cursorPos) |
|
|
|
return; |
|
|
|
gw2obj->cursorPos--; |
|
|
|
TextEditRemoveChar(gw); |
|
|
|
break; |
|
|
|
case GKEY_TAB: |
|
|
|
case GKEY_LF: |
|
|
|
case GKEY_CR: |
|
|
|
// Move to the next field
|
|
|
|
_gwinMoveFocus(); |
|
|
|
return; |
|
|
|
case GKEY_DEL: |
|
|
|
// Delete
|
|
|
|
if (!gw->text[gw2obj->cursorPos]) |
|
|
|
return; |
|
|
|
TextEditRemoveChar(gw); |
|
|
|
break; |
|
|
|
default: |
|
|
|
// Ignore any other control characters
|
|
|
|
if ((uint8_t)pke->c[0] < GKEY_SPACE) |
|
|
|
return; |
|
|
|
|
|
|
|
// Keep the edit length to less than the maximum
|
|
|
|
if (gw2obj->maxSize && strlen(gw->text)+pke->bytecount > gw2obj->maxSize) |
|
|
|
return; |
|
|
|
|
|
|
|
// Make space
|
|
|
|
if (TextEditAddChars(gw, pke->bytecount)) { |
|
|
|
// Insert the characters
|
|
|
|
memcpy((char *)gw->text+gw2obj->cursorPos, pke->c, pke->bytecount); |
|
|
|
gw2obj->cursorPos += pke->bytecount; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
_gwinUpdate((GHandle)gw); |
|
|
|
gwinTextEditSendKey(&gw->g, pke->c, pke->bytecount); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
@ -246,6 +183,89 @@ GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit |
|
|
|
return (GHandle)wt; |
|
|
|
} |
|
|
|
|
|
|
|
#if (GFX_USE_GINPUT && GINPUT_NEED_KEYBOARD) || GWIN_NEED_KEYBOARD |
|
|
|
void gwinTextEditSendSpecialKey(GHandle gh, uint8_t key) { |
|
|
|
// Is it a valid handle?
|
|
|
|
if (gh->vmt != (gwinVMT*)&texteditVMT) |
|
|
|
return; |
|
|
|
|
|
|
|
// Arrow keys to move the cursor
|
|
|
|
switch (key) { |
|
|
|
case GKEY_LEFT: |
|
|
|
if (!gh2obj->cursorPos) |
|
|
|
return; |
|
|
|
gh2obj->cursorPos--; |
|
|
|
break; |
|
|
|
case GKEY_RIGHT: |
|
|
|
if (!gh2obj->w.text[gh2obj->cursorPos]) |
|
|
|
return; |
|
|
|
gh2obj->cursorPos++; |
|
|
|
break; |
|
|
|
case GKEY_HOME: |
|
|
|
if (!gh2obj->cursorPos) |
|
|
|
return; |
|
|
|
gh2obj->cursorPos = 0; |
|
|
|
break; |
|
|
|
case GKEY_END: |
|
|
|
if (!gh2obj->w.text[gh2obj->cursorPos]) |
|
|
|
return; |
|
|
|
gh2obj->cursorPos = strlen(gh2obj->w.text); |
|
|
|
break; |
|
|
|
default: |
|
|
|
return; |
|
|
|
} |
|
|
|
|
|
|
|
_gwinUpdate(gh); |
|
|
|
} |
|
|
|
|
|
|
|
void gwinTextEditSendKey(GHandle gh, char *key, unsigned len) { |
|
|
|
// Is it a valid handle?
|
|
|
|
if (gh->vmt != (gwinVMT*)&texteditVMT || !key || !len) |
|
|
|
return; |
|
|
|
|
|
|
|
// Normal key press
|
|
|
|
switch((uint8_t)key[0]) { |
|
|
|
case GKEY_BACKSPACE: |
|
|
|
// Backspace
|
|
|
|
if (!gh2obj->cursorPos) |
|
|
|
return; |
|
|
|
gh2obj->cursorPos--; |
|
|
|
TextEditRemoveChar(gh); |
|
|
|
break; |
|
|
|
case GKEY_TAB: |
|
|
|
case GKEY_LF: |
|
|
|
case GKEY_CR: |
|
|
|
// Move to the next field
|
|
|
|
_gwinMoveFocus(); |
|
|
|
return; |
|
|
|
case GKEY_DEL: |
|
|
|
// Delete
|
|
|
|
if (!gh2obj->w.text[gh2obj->cursorPos]) |
|
|
|
return; |
|
|
|
TextEditRemoveChar(gh); |
|
|
|
break; |
|
|
|
default: |
|
|
|
// Ignore any other control characters
|
|
|
|
if ((uint8_t)key[0] < GKEY_SPACE) |
|
|
|
return; |
|
|
|
|
|
|
|
// Keep the edit length to less than the maximum
|
|
|
|
if (gh2obj->maxSize && strlen(gh2obj->w.text)+len > gh2obj->maxSize) |
|
|
|
return; |
|
|
|
|
|
|
|
// Make space
|
|
|
|
if (TextEditAddChars(gh, len)) { |
|
|
|
// Insert the characters
|
|
|
|
memcpy((char *)gh2obj->w.text+gh2obj->cursorPos, key, len); |
|
|
|
gh2obj->cursorPos += len; |
|
|
|
} |
|
|
|
break; |
|
|
|
} |
|
|
|
|
|
|
|
_gwinUpdate(gh); |
|
|
|
} |
|
|
|
#endif |
|
|
|
|
|
|
|
void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param) |
|
|
|
{ |
|
|
|
const char* p; |
|
|
|