2 * Acess2 Window Manager v3
3 * - By John Hodge (thePowersGang)
5 * renderer/widget/textinput.c
6 * - Single line text box
8 * TODO: Support Right-to-Left text
12 #include "./colours.h"
16 // TODO: Include a proper keysym header
17 #define KEYSYM_LEFTARROW 0x50
18 #define KEYSYM_RIGHTARROW 0x4F
22 int DrawOfs; // Byte offset for the leftmost character
23 int CursorXOfs; // Pixel offset of the cursor
30 const int ciTextInput_MarginT = 3;
31 const int ciTextInput_MarginB = 3;
32 const int ciTextInput_MarginV = 6; // Sum of above
33 const int ciTextInput_MarginL = 3;
34 const int ciTextInput_MarginR = 3;
35 const int ciTextInput_MarginH = 6;
38 tFont *gpTextInput_Font = NULL;
41 void Widget_TextInput_Render(tWindow *Window, tElement *Element)
43 struct sTextInputInfo *info = (void*)Element->Data;
44 struct sWidgetWin *wininfo = Window->RendererInfo;
46 // Scroll view when X offset reaches either end
47 while(info->CursorXOfs >= Element->CachedW - ciTextInput_MarginH)
51 info->DrawOfs += ReadUTF8( &Element->Text[info->DrawOfs], &cp );
52 WM_Render_GetTextDims(
54 &Element->Text[info->DrawOfs], info->CursorByteOfs - info->DrawOfs,
59 if(info->CursorXOfs < 0)
61 info->DrawOfs = info->CursorByteOfs;
67 WM_Render_FillRect(Window,
68 Element->CachedX, Element->CachedY,
69 Element->CachedW, Element->CachedH,
72 WM_Render_DrawRect(Window,
73 Element->CachedX, Element->CachedY,
74 Element->CachedW, Element->CachedH,
77 WM_Render_DrawRect(Window,
78 Element->CachedX+1, Element->CachedY+1,
79 Element->CachedW-2, Element->CachedH-2,
85 WM_Render_DrawText(Window,
86 Element->CachedX+ciTextInput_MarginL, Element->CachedY+ciTextInput_MarginT,
87 Element->CachedW-ciTextInput_MarginH, Element->CachedH-ciTextInput_MarginV,
88 gpTextInput_Font, TEXTINPUT_TEXT,
89 &Element->Text[info->DrawOfs], -1
93 if( wininfo->FocusedElement == Element )
95 WM_Render_SetTextCursor(Window,
96 Element->CachedX+ciTextInput_MarginL+info->CursorXOfs,
97 Element->CachedY+ciTextInput_MarginR,
98 1, Element->CachedH-ciTextInput_MarginV,
104 void Widget_TextInput_Init(tElement *Element)
106 struct sTextInputInfo *info;
109 // TODO: Select font correctly
110 WM_Render_GetTextDims(gpTextInput_Font, "jy|qJ", -1, NULL, &h);
112 h += ciTextInput_MarginV; // Border padding
115 Element->MinW = ciTextInput_MarginH;
117 info = Element->Data = malloc(sizeof(*info));
119 info->CursorXOfs = 0;
121 // No need to explicitly update parent min dims, as the AddElement routine does that
124 int Widget_TextInput_KeyFire(tElement *Element, int KeySym, int Character)
126 struct sTextInputInfo *info = Element->Data;
132 // _SysDebug("Key 0x%x fired ('%c')", Character, Character);
138 case KEYSYM_LEFTARROW:
139 if( info->CursorByteOfs > 0 )
141 len = ReadUTF8Rev(Element->Text, info->CursorByteOfs, &cp);
142 info->CursorByteOfs -= len;
143 WM_Render_GetTextDims(
145 Element->Text+info->CursorByteOfs,
148 info->CursorXOfs -= w;
151 case KEYSYM_RIGHTARROW:
152 if( info->CursorByteOfs < info->Length )
154 len = ReadUTF8(Element->Text + info->CursorByteOfs, &cp);
155 WM_Render_GetTextDims(
157 Element->Text+info->CursorByteOfs,
160 info->CursorByteOfs += len;
161 info->CursorXOfs += w;
168 // TODO: Don't hard code
169 if(Character > 0x30000000) return 0;
177 // Check if there is anything to delete
178 if( info->CursorByteOfs == 0 ) return 0;
179 // Get character to be deleted
180 len = ReadUTF8Rev(Element->Text, info->CursorByteOfs, &cp);
181 info->CursorByteOfs -= len;
182 dest = &Element->Text[info->CursorByteOfs];
183 // _SysDebug("\\b, len = %i, removing '%.*s'", len, len, dest);
184 WM_Render_GetTextDims(gpTextInput_Font, dest, len, &w, 0);
185 // Remove from buffer
186 memmove(dest, &dest[len], info->Length - info->CursorByteOfs - len);
188 Element->Text[info->Length] = '\0';
190 info->CursorXOfs -= w;
193 if(Character >= 0x30000000) return 0;
194 if(Character < ' ') return 0;
196 // Get required length
197 len = WriteUTF8(NULL, Character);
199 // Create space (possibly in the middle)
200 Element->Text = realloc(Element->Text, info->Length + len + 1);
201 dest = &Element->Text[info->CursorByteOfs];
202 memmove(&dest[len], dest, info->Length - info->CursorByteOfs);
204 WriteUTF8(dest, Character);
205 info->CursorByteOfs += len;
207 Element->Text[info->Length] = '\0';
209 // Update the cursor position
210 // - Scrolling is implemented in render function (CachedW/CachedH are invalid atm)
211 WM_Render_GetTextDims(gpTextInput_Font, dest, len, &w, NULL);
212 info->CursorXOfs += w;
215 // TODO: Have a Widget_ function to do this instead
216 WM_Invalidate(Element->Window, 1);
221 DEFWIDGETTYPE(ELETYPE_TEXTINPUT,
222 WIDGETTYPE_FLAG_NOCHILDREN,
223 .Render = Widget_TextInput_Render,
224 .Init = Widget_TextInput_Init,
225 .KeyFire = Widget_TextInput_KeyFire