Add gwinTextEditSendKey() and gwinTextEditSendSpecialKey()

This commit is contained in:
inmarket 2017-08-26 11:15:56 +10:00
parent 04c23b408d
commit 0388755df1
3 changed files with 132 additions and 85 deletions

View File

@ -47,6 +47,7 @@ REMOVED: Removed long deprecated functions gfxSemCounter() and gfxSemCounterI()
FIX: gwinDetachToggle() is now a visible part of the API
CHANGE: Update OSX makefiles (allows for 64bit building)
FIX: Fixed resetting a timer on gwinImage objects when using animated GIFs
FEATURE: Added gwinTextEditSendKey() and gwinTextEditSendSpecialKey()
*** Release 2.7 ***

View File

@ -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;
}
gwinTextEditSendSpecialKey(&gw->g, (uint8_t)pke->c[0]);
return;
} else {
// 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;

View File

@ -63,6 +63,32 @@ extern "C" {
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize);
#define gwinTexteditCreate(wt, pInit, maxSize) gwinGTexteditCreate(GDISP, wt, pInit, maxSize)
/**
* @brief Send a special key to the textedit such as GKEY_LEFT, GKEY_RIGHT, GKEY_HOME, GKEY_END
*
* @param[in] gh The window handle (must be a textedit window)
* @param[in] key The special key to send.
* @pre Requires GINPUT_NEED_KEYBOARD or GWIN_NEED_KEYBOARD to be on
* @api
*/
void gwinTextEditSendSpecialKey(GHandle gh, uint8_t key);
/**
* @brief Send a normal utf8 character to the textedit
*
* @param[in] gh The window handle (must be a textedit window)
* @param[in] pkey The pointer to the utf8 character to send.
* @param[in] len The length of the utf8 character in bytes.
* @note This must ONLY be called with a single utf8 character at a time. Don't attempt to
* send a string of characters in the one call.
* @note Characters are interpreted as if they came directly from a keyboard ie a backspace
* character will perform the backspace operation, a tab will send the focus to the next
* control etc.
* @pre Requires GINPUT_NEED_KEYBOARD or GWIN_NEED_KEYBOARD to be on
* @api
*/
void gwinTextEditSendKey(GHandle gh, char *pkey, unsigned len);
/**
* @defgroup Renderings_Textedit Renderings
*