Add gwinTextEditSendKey() and gwinTextEditSendSpecialKey()
This commit is contained in:
parent
04c23b408d
commit
0388755df1
3 changed files with 132 additions and 85 deletions
|
@ -47,6 +47,7 @@ REMOVED: Removed long deprecated functions gfxSemCounter() and gfxSemCounterI()
|
||||||
FIX: gwinDetachToggle() is now a visible part of the API
|
FIX: gwinDetachToggle() is now a visible part of the API
|
||||||
CHANGE: Update OSX makefiles (allows for 64bit building)
|
CHANGE: Update OSX makefiles (allows for 64bit building)
|
||||||
FIX: Fixed resetting a timer on gwinImage objects when using animated GIFs
|
FIX: Fixed resetting a timer on gwinImage objects when using animated GIFs
|
||||||
|
FEATURE: Added gwinTextEditSendKey() and gwinTextEditSendSpecialKey()
|
||||||
|
|
||||||
|
|
||||||
*** Release 2.7 ***
|
*** Release 2.7 ***
|
||||||
|
|
|
@ -26,54 +26,54 @@
|
||||||
#define gh2obj ((GTexteditObject *)gh)
|
#define gh2obj ((GTexteditObject *)gh)
|
||||||
#define gw2obj ((GTexteditObject *)gw)
|
#define gw2obj ((GTexteditObject *)gw)
|
||||||
|
|
||||||
static void TextEditRemoveChar(GWidgetObject* gw) {
|
static void TextEditRemoveChar(GHandle gh) {
|
||||||
char *p;
|
char *p;
|
||||||
const char *q;
|
const char *q;
|
||||||
unsigned sz;
|
unsigned sz;
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
|
|
||||||
sz = strlen(gw->text);
|
sz = strlen(gh2obj->w.text);
|
||||||
pos = gw2obj->cursorPos;
|
pos = gh2obj->cursorPos;
|
||||||
q = gw->text+pos;
|
q = gh2obj->w.text+pos;
|
||||||
|
|
||||||
if (!(gw->g.flags & GWIN_FLG_ALLOCTXT)) {
|
if (!(gh->flags & GWIN_FLG_ALLOCTXT)) {
|
||||||
// Allocate and then copy
|
// Allocate and then copy
|
||||||
if (!(p = gfxAlloc(sz)))
|
if (!(p = gfxAlloc(sz)))
|
||||||
return;
|
return;
|
||||||
if (pos)
|
if (pos)
|
||||||
memcpy(p, gw->text, pos);
|
memcpy(p, gh2obj->w.text, pos);
|
||||||
memcpy(p+pos, q+1, sz-pos);
|
memcpy(p+pos, q+1, sz-pos);
|
||||||
gw->g.flags |= GWIN_FLG_ALLOCTXT;
|
gh->flags |= GWIN_FLG_ALLOCTXT;
|
||||||
} else {
|
} else {
|
||||||
// Copy and then reallocate
|
// Copy and then reallocate
|
||||||
memcpy((char *)q, q+1, sz-pos);
|
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;
|
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;
|
char *p;
|
||||||
const char *q;
|
const char *q;
|
||||||
unsigned sz;
|
unsigned sz;
|
||||||
unsigned pos;
|
unsigned pos;
|
||||||
|
|
||||||
// Get the size of the text buffer
|
// Get the size of the text buffer
|
||||||
sz = strlen(gw->text)+1;
|
sz = strlen(gh2obj->w.text)+1;
|
||||||
pos = gw2obj->cursorPos;
|
pos = gh2obj->cursorPos;
|
||||||
|
|
||||||
if (!(gw->g.flags & GWIN_FLG_ALLOCTXT)) {
|
if (!(gh->flags & GWIN_FLG_ALLOCTXT)) {
|
||||||
if (!(p = gfxAlloc(sz+cnt)))
|
if (!(p = gfxAlloc(sz+cnt)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
memcpy(p, gw->text, pos);
|
memcpy(p, gh2obj->w.text, pos);
|
||||||
memcpy(p+pos+cnt, gw->text+pos, sz-pos);
|
memcpy(p+pos+cnt, gh2obj->w.text+pos, sz-pos);
|
||||||
gw->g.flags |= GWIN_FLG_ALLOCTXT;
|
gh->flags |= GWIN_FLG_ALLOCTXT;
|
||||||
gw->text = p;
|
gh2obj->w.text = p;
|
||||||
} else {
|
} else {
|
||||||
if (!(p = gfxRealloc((char *)gw->text, sz, sz+cnt)))
|
if (!(p = gfxRealloc((char *)gh2obj->w.text, sz, sz+cnt)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
gw->text = p;
|
gh2obj->w.text = p;
|
||||||
q = p+pos;
|
q = p+pos;
|
||||||
p += sz;
|
p += sz;
|
||||||
while(--p >= q)
|
while(--p >= q)
|
||||||
|
@ -117,76 +117,13 @@ static void TextEditMouseDown(GWidgetObject* gw, coord_t x, coord_t y) {
|
||||||
|
|
||||||
// Is it a special key?
|
// Is it a special key?
|
||||||
if (pke->keystate & GKEYSTATE_SPECIAL) {
|
if (pke->keystate & GKEYSTATE_SPECIAL) {
|
||||||
|
|
||||||
// Arrow keys to move the cursor
|
// Arrow keys to move the cursor
|
||||||
switch ((uint8_t)pke->c[0]) {
|
gwinTextEditSendSpecialKey(&gw->g, (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;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
gwinTextEditSendKey(&gw->g, pke->c, pke->bytecount);
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -246,6 +183,89 @@ GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit
|
||||||
return (GHandle)wt;
|
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)
|
void gwinTexteditDefaultDraw(GWidgetObject* gw, void* param)
|
||||||
{
|
{
|
||||||
const char* p;
|
const char* p;
|
||||||
|
|
|
@ -63,6 +63,32 @@ extern "C" {
|
||||||
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize);
|
GHandle gwinGTexteditCreate(GDisplay* g, GTexteditObject* wt, GWidgetInit* pInit, size_t maxSize);
|
||||||
#define gwinTexteditCreate(wt, pInit, maxSize) gwinGTexteditCreate(GDISP, wt, pInit, 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
|
* @defgroup Renderings_Textedit Renderings
|
||||||
*
|
*
|
||||||
|
|
Loading…
Add table
Reference in a new issue