+int Widget_TextInput_KeyFire(tElement *Element, int KeySym, int Character)
+{
+ struct sTextInputInfo *info = Element->Data;
+ int len;
+ int w;
+ char *dest;
+ uint32_t cp;
+
+// _SysDebug("Key 0x%x fired ('%c')", Character, Character);
+
+ if( Character == 0 )
+ {
+ switch(KeySym)
+ {
+ case KEYSYM_LEFTARROW:
+ if( info->CursorByteOfs > 0 )
+ {
+ len = ReadUTF8Rev(Element->Text, info->CursorByteOfs, &cp);
+ info->CursorByteOfs -= len;
+ WM_Render_GetTextDims(
+ gpTextInput_Font,
+ Element->Text+info->CursorByteOfs,
+ len, &w, 0
+ );
+ info->CursorXOfs -= w;
+ }
+ break;
+ case KEYSYM_RIGHTARROW:
+ if( info->CursorByteOfs < info->Length )
+ {
+ len = ReadUTF8(Element->Text + info->CursorByteOfs, &cp);
+ WM_Render_GetTextDims(
+ gpTextInput_Font,
+ Element->Text+info->CursorByteOfs,
+ len, &w, 0
+ );
+ info->CursorByteOfs += len;
+ info->CursorXOfs += w;
+ }
+ break;
+ }
+ return 0;
+ }
+
+ // TODO: Don't hard code
+ if(Character > 0x30000000) return 0;
+
+ switch(Character)
+ {
+ case '\t':
+ return 0;
+
+ case '\b':
+ // Check if there is anything to delete
+ if( info->CursorByteOfs == 0 ) return 0;
+ // Get character to be deleted
+ len = ReadUTF8Rev(Element->Text, info->CursorByteOfs, &cp);
+ info->CursorByteOfs -= len;
+ dest = &Element->Text[info->CursorByteOfs];
+// _SysDebug("\\b, len = %i, removing '%.*s'", len, len, dest);
+ WM_Render_GetTextDims(gpTextInput_Font, dest, len, &w, 0);
+ // Remove from buffer
+ memmove(dest, &dest[len], info->Length - info->CursorByteOfs - len);
+ info->Length -= len;
+ Element->Text[info->Length] = '\0';
+ // Adjust cursor
+ info->CursorXOfs -= w;
+ break;
+ default:
+ if(Character >= 0x30000000) return 0;
+ if(Character < ' ') return 0;
+
+ // Get required length
+ len = WriteUTF8(NULL, Character);
+
+ // Create space (possibly in the middle)
+ Element->Text = realloc(Element->Text, info->Length + len + 1);
+ dest = &Element->Text[info->CursorByteOfs];
+ memmove(&dest[len], dest, info->Length - info->CursorByteOfs);
+ // Add the character
+ WriteUTF8(dest, Character);
+ info->CursorByteOfs += len;
+ info->Length += len;
+ Element->Text[info->Length] = '\0';
+
+ // Update the cursor position
+ // - Scrolling is implemented in render function (CachedW/CachedH are invalid atm)
+ WM_Render_GetTextDims(gpTextInput_Font, dest, len, &w, NULL);
+ info->CursorXOfs += w;
+ }
+
+ // TODO: Have a Widget_ function to do this instead
+ WM_Invalidate(Element->Window, 1);
+
+ return 0;
+}
+
+DEFWIDGETTYPE(ELETYPE_TEXTINPUT, "TextInput",