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"
18 int DrawOfs; // Byte offset for the leftmost character
19 int CursorXOfs; // Pixel offset of the cursor
26 const int ciTextInput_MarginT = 3;
27 const int ciTextInput_MarginB = 3;
28 const int ciTextInput_MarginV = 6; // Sum of above
29 const int ciTextInput_MarginL = 3;
30 const int ciTextInput_MarginR = 3;
31 const int ciTextInput_MarginH = 6;
34 tFont *gpTextInput_Font = NULL;
37 void Widget_TextInput_Render(tWindow *Window, tElement *Element)
39 struct sTextInputInfo *info = (void*)Element->Data;
40 struct sWidgetWin *wininfo = Window->RendererInfo;
42 // Scroll view when X offset reaches either end
43 while(info->CursorXOfs >= Element->CachedW - ciTextInput_MarginH)
47 info->DrawOfs += ReadUTF8( &Element->Text[info->DrawOfs], &cp );
48 WM_Render_GetTextDims(
50 &Element->Text[info->DrawOfs], info->CursorByteOfs - info->DrawOfs,
55 if(info->CursorXOfs < 0)
57 info->DrawOfs = info->CursorByteOfs;
63 WM_Render_FillRect(Window,
64 Element->CachedX, Element->CachedY,
65 Element->CachedW, Element->CachedH,
68 WM_Render_DrawRect(Window,
69 Element->CachedX, Element->CachedY,
70 Element->CachedW, Element->CachedH,
73 WM_Render_DrawRect(Window,
74 Element->CachedX+1, Element->CachedY+1,
75 Element->CachedW-2, Element->CachedH-2,
81 WM_Render_DrawText(Window,
82 Element->CachedX+ciTextInput_MarginL, Element->CachedY+ciTextInput_MarginT,
83 Element->CachedW-ciTextInput_MarginH, Element->CachedH-ciTextInput_MarginV,
84 gpTextInput_Font, TEXTINPUT_TEXT,
85 &Element->Text[info->DrawOfs], -1
89 if( wininfo->FocusedElement == Element )
91 WM_Render_SetTextCursor(Window,
92 Element->CachedX+ciTextInput_MarginL+info->CursorXOfs,
93 Element->CachedY+ciTextInput_MarginR,
94 1, Element->CachedH-ciTextInput_MarginV,
100 void Widget_TextInput_Init(tElement *Element)
102 struct sTextInputInfo *info;
105 // TODO: Select font correctly
106 WM_Render_GetTextDims(gpTextInput_Font, "jy|qJ", -1, NULL, &h);
108 h += ciTextInput_MarginV; // Border padding
111 Element->MinW = ciTextInput_MarginH;
113 info = Element->Data = malloc(sizeof(*info));
115 info->CursorXOfs = 0;
117 // No need to explicitly update parent min dims, as the AddElement routine does that
120 int Widget_TextInput_KeyFire(tElement *Element, int KeySym, int Character)
122 struct sTextInputInfo *info = Element->Data;
128 // _SysDebug("Key 0x%x fired ('%c')", Character, Character);
133 // TODO: Don't hard code
134 if(Character > 0x30000000) return 0;
142 // Check if there is anything to delete
143 if( info->CursorByteOfs == 0 ) return 0;
144 // Get character to be deleted
145 len = ReadUTF8Rev(Element->Text, info->CursorByteOfs, &cp);
146 info->CursorByteOfs -= len;
147 dest = &Element->Text[info->CursorByteOfs];
148 // _SysDebug("\\b, len = %i, removing '%.*s'", len, len, dest);
149 WM_Render_GetTextDims(gpTextInput_Font, dest, len, &w, 0);
150 // Remove from buffer
151 memmove(dest, &dest[len], info->Length - info->CursorByteOfs - len);
153 Element->Text[info->Length] = '\0';
155 info->CursorXOfs -= w;
158 if(Character >= 0x30000000) return 0;
159 if(Character < ' ') return 0;
161 // Get required length
162 len = WriteUTF8(NULL, Character);
164 // Create space (possibly in the middle)
165 Element->Text = realloc(Element->Text, info->Length + len + 1);
166 dest = &Element->Text[info->CursorByteOfs];
167 memmove(&dest[len], dest, info->Length - info->CursorByteOfs);
169 WriteUTF8(dest, Character);
170 info->CursorByteOfs += len;
172 Element->Text[info->Length] = '\0';
174 // Update the cursor position
175 // - Scrolling is implemented in render function (CachedW/CachedH are invalid atm)
176 WM_Render_GetTextDims(gpTextInput_Font, dest, len, &w, NULL);
177 info->CursorXOfs += w;
180 // TODO: Have a Widget_ function to do this instead
181 WM_Invalidate(Element->Window);
186 DEFWIDGETTYPE(ELETYPE_TEXTINPUT,
187 WIDGETTYPE_FLAG_NOCHILDREN,
188 .Render = Widget_TextInput_Render,
189 .Init = Widget_TextInput_Init,
190 .KeyFire = Widget_TextInput_KeyFire