blob: 4bf01ada21901dbc704eadbb443e04c94ff1958a [file] [log] [blame]
Dees Troy3be70a82013-10-22 14:25:12 +00001/*
Ethan Yonkera5db7122016-03-14 15:47:09 -05002 Copyright 2012 to 2016 bigbiff/Dees_Troy TeamWin
Dees Troy3be70a82013-10-22 14:25:12 +00003 This file is part of TWRP/TeamWin Recovery Project.
4
5 TWRP is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 TWRP is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with TWRP. If not, see <http://www.gnu.org/licenses/>.
17*/
18
Dees_Troy51a0e822012-09-05 15:24:24 -040019// input.cpp - GUIInput object
20
21#include <linux/input.h>
22#include <pthread.h>
23#include <stdarg.h>
24#include <stdio.h>
25#include <stdlib.h>
26#include <string.h>
27#include <fcntl.h>
28#include <sys/reboot.h>
29#include <sys/stat.h>
30#include <sys/time.h>
31#include <sys/mman.h>
32#include <sys/types.h>
33#include <sys/ioctl.h>
34#include <time.h>
35#include <unistd.h>
36#include <stdlib.h>
37
38#include <string>
39
40extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000041#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040042}
Ethan Yonkerfbb43532015-12-28 21:54:50 +010043#include "../minuitwrp/minui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040044
45#include "rapidxml.hpp"
46#include "objects.hpp"
47#include "../data.hpp"
48
Ethan Yonkera5db7122016-03-14 15:47:09 -050049#define TW_INPUT_NO_UPDATE -1000 // Magic value for HandleTextLocation when no change in scrolling has occurred
50
Dees_Troy51a0e822012-09-05 15:24:24 -040051GUIInput::GUIInput(xml_node<>* node)
Vojtech Bocekede51c52014-02-07 23:58:09 +010052 : GUIObject(node)
Dees_Troy51a0e822012-09-05 15:24:24 -040053{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020054 xml_attribute<>* attr;
55 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -040056
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020057 mInputText = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040058 mAction = NULL;
59 mBackground = NULL;
60 mCursor = NULL;
61 mFont = NULL;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020062 mRendered = false;
Dees_Troy51a0e822012-09-05 15:24:24 -040063 HasMask = false;
64 DrawCursor = false;
65 isLocalChange = true;
66 HasAllowed = false;
67 HasDisabled = false;
Ethan Yonkera5db7122016-03-14 15:47:09 -050068 cursorX = textWidth = scrollingX = mFontHeight = mFontY = lastX = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -040069 mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = MinLen = MaxLen = 0;
70 mCursorLocation = -1; // -1 is always the end of the string
71 CursorWidth = 3;
72 ConvertStrToColor("black", &mBackgroundColor);
73 ConvertStrToColor("white", &mCursorColor);
Ethan Yonkera5db7122016-03-14 15:47:09 -050074 displayValue = "";
Dees_Troy51a0e822012-09-05 15:24:24 -040075
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020076 if (!node)
77 return;
Dees_Troy51a0e822012-09-05 15:24:24 -040078
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020079 // Load text directly from the node
80 mInputText = new GUIText(node);
Dees_Troy51a0e822012-09-05 15:24:24 -040081 // Load action directly from the node
82 mAction = new GUIAction(node);
83
84 if (mInputText->Render() < 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020085 {
86 delete mInputText;
87 mInputText = NULL;
88 }
Dees_Troy51a0e822012-09-05 15:24:24 -040089
90 // Load the background
Ethan Yonker21ff02a2015-02-18 14:35:00 -060091 child = FindNode(node, "background");
Dees_Troy51a0e822012-09-05 15:24:24 -040092 if (child)
93 {
thatf6ed8fc2015-02-14 20:23:16 +010094 mBackground = LoadAttrImage(child, "resource");
95 mBackgroundColor = LoadAttrColor(child, "color", mBackgroundColor);
Dees_Troy51a0e822012-09-05 15:24:24 -040096 }
97 if (mBackground && mBackground->GetResource())
98 {
thatf6ed8fc2015-02-14 20:23:16 +010099 mBackgroundW = mBackground->GetWidth();
100 mBackgroundH = mBackground->GetHeight();
Dees_Troy51a0e822012-09-05 15:24:24 -0400101 }
102
103 // Load the cursor color
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600104 child = FindNode(node, "cursor");
Dees_Troy51a0e822012-09-05 15:24:24 -0400105 if (child)
106 {
thatf6ed8fc2015-02-14 20:23:16 +0100107 mCursor = LoadAttrImage(child, "resource");
108 mCursorColor = LoadAttrColor(child, "color", mCursorColor);
Dees_Troy51a0e822012-09-05 15:24:24 -0400109 attr = child->first_attribute("hasfocus");
110 if (attr)
111 {
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600112 std::string focus = attr->value();
113 SetInputFocus(atoi(focus.c_str()));
Dees_Troy51a0e822012-09-05 15:24:24 -0400114 }
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600115 CursorWidth = LoadAttrIntScaleX(child, "width", CursorWidth);
Dees_Troy51a0e822012-09-05 15:24:24 -0400116 }
117 DrawCursor = HasInputFocus;
118
thatf6ed8fc2015-02-14 20:23:16 +0100119 // Load the font
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600120 child = FindNode(node, "font");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200121 if (child)
122 {
thatf6ed8fc2015-02-14 20:23:16 +0100123 mFont = LoadAttrFont(child, "resource");
124 mFontHeight = mFont->GetHeight();
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200125 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400126
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600127 child = FindNode(node, "text");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200128 if (child) mText = child->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400129 mLastValue = gui_parse_text(mText);
130
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600131 child = FindNode(node, "data");
Dees_Troy51a0e822012-09-05 15:24:24 -0400132 if (child)
133 {
134 attr = child->first_attribute("name");
135 if (attr)
136 mVariable = attr->value();
137 attr = child->first_attribute("default");
138 if (attr)
139 DataManager::SetValue(mVariable, attr->value());
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600140 mMask = LoadAttrString(child, "mask");
141 HasMask = !mMask.empty();
Dees_Troy51a0e822012-09-05 15:24:24 -0400142 }
143
144 // Load input restrictions
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600145 child = FindNode(node, "restrict");
Dees_Troy51a0e822012-09-05 15:24:24 -0400146 if (child)
147 {
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600148 MinLen = LoadAttrInt(child, "minlen", MinLen);
149 MaxLen = LoadAttrInt(child, "maxlen", MaxLen);
150 AllowedList = LoadAttrString(child, "allow");
151 HasAllowed = !AllowedList.empty();
152 DisabledList = LoadAttrString(child, "disable");
153 HasDisabled = !DisabledList.empty();
Dees_Troy51a0e822012-09-05 15:24:24 -0400154 }
155
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200156 // Load the placement
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600157 LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
Dees_Troy51a0e822012-09-05 15:24:24 -0400158 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
159
160 if (mInputText && mFontHeight && mFontHeight < (unsigned)mRenderH) {
161 mFontY = ((mRenderH - mFontHeight) / 2) + mRenderY;
162 mInputText->SetRenderPos(mRenderX, mFontY);
163 } else
164 mFontY = mRenderY;
165
166 if (mInputText)
Ethan Yonkera5db7122016-03-14 15:47:09 -0500167 mInputText->SetMaxWidth(0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400168}
169
170GUIInput::~GUIInput()
171{
thatf6ed8fc2015-02-14 20:23:16 +0100172 delete mInputText;
173 delete mAction;
Dees_Troy51a0e822012-09-05 15:24:24 -0400174}
175
Ethan Yonkera5db7122016-03-14 15:47:09 -0500176void GUIInput::HandleTextLocation(int x) {
177 mRendered = false;
178 if (textWidth <= mRenderW) {
179 if (x != TW_INPUT_NO_UPDATE)
180 lastX = x;
181 scrollingX = 0;
182 return;
183 }
184 if (scrollingX + textWidth < mRenderW) {
185 scrollingX = mRenderW - textWidth;
186 }
187
188 if (x == TW_INPUT_NO_UPDATE)
189 return;
190
191 scrollingX += x - lastX;
192 if (scrollingX > 0)
193 scrollingX = 0;
194 else if (scrollingX + textWidth < mRenderW)
195 scrollingX = mRenderW - textWidth;
196 lastX = x;
197}
198
199void GUIInput::UpdateTextWidth() {
Dees_Troy51a0e822012-09-05 15:24:24 -0400200 void* fontResource = NULL;
201
Ethan Yonkera5db7122016-03-14 15:47:09 -0500202 if (mFont) {
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200203 fontResource = mFont->GetResource();
Ethan Yonkera5db7122016-03-14 15:47:09 -0500204 } else {
205 textWidth = 0;
206 return;
207 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400208
Ethan Yonkera5db7122016-03-14 15:47:09 -0500209 DataManager::GetValue(mVariable, displayValue);
Dees_Troy51a0e822012-09-05 15:24:24 -0400210 if (HasMask) {
211 int index, string_size = displayValue.size();
212 string maskedValue;
213 for (index=0; index<string_size; index++)
214 maskedValue += mMask;
215 displayValue = maskedValue;
216 }
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100217 textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
Ethan Yonkera5db7122016-03-14 15:47:09 -0500218}
219
220void GUIInput::HandleCursorByTouch(int x) {
221// Uses x to find mCursorLocation and cursorX
222 if (displayValue.size() == 0) {
223 mCursorLocation = -1;
224 cursorX = mRenderX;
225 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400226 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200227
Ethan Yonkera5db7122016-03-14 15:47:09 -0500228 void* fontResource = NULL;
229 if (mFont) {
230 fontResource = mFont->GetResource();
231 } else {
232 return;
233 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200234
Ethan Yonkera5db7122016-03-14 15:47:09 -0500235 string cursorString;
236 unsigned index = 0, displaySize = displayValue.size();
237 int prevX = mRenderX + scrollingX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400238
Ethan Yonkera5db7122016-03-14 15:47:09 -0500239 for(index = 0; index <= displaySize; index++) {
240 cursorString = displayValue.substr(0, index);
241 cursorX = gr_ttf_measureEx(cursorString.c_str(), fontResource) + mRenderX + scrollingX;
242 if (cursorX > x) {
243 if (index > 0 && x <= cursorX - ((x - prevX) / 2) && prevX >= mRenderX) {
244 // This helps make sure that we can place the cursor before the very first char if the first char is
245 // is fully visible while also still letting us place the cursor after the last char if fully visible
246 mCursorLocation = index - 1;
247 cursorX = prevX;
248 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400249 }
Ethan Yonkera5db7122016-03-14 15:47:09 -0500250 mCursorLocation = index;
251 if (cursorX > mRenderX + mRenderW) {
252 cursorX = prevX; // This makes sure that the cursor doesn't get placed after the end of the input box
Dees_Troy51a0e822012-09-05 15:24:24 -0400253 mCursorLocation--;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500254 return;
Dees_Troy51a0e822012-09-05 15:24:24 -0400255 }
Ethan Yonkera5db7122016-03-14 15:47:09 -0500256 if (cursorX >= mRenderX) {
257 return; // This makes sure that the cursor doesn't get placed before the beginning of the input box
Dees_Troy51a0e822012-09-05 15:24:24 -0400258 }
259 }
Ethan Yonkera5db7122016-03-14 15:47:09 -0500260 prevX = cursorX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400261 }
Ethan Yonkera5db7122016-03-14 15:47:09 -0500262 mCursorLocation = -1; // x is at or past the end of the string
263}
264
265void GUIInput::HandleCursorByText() {
266// Uses mCursorLocation to find cursorX
267 if (!DrawCursor)
268 return;
269
270 void* fontResource = NULL;
271 if (mFont) {
272 fontResource = mFont->GetResource();
273 } else {
274 return;
275 }
276
277 int cursorWidth = textWidth;
278
279 if (mCursorLocation != -1) {
280 string cursorDisplay = displayValue;
281 cursorDisplay.resize(mCursorLocation);
282 cursorWidth = gr_ttf_measureEx(cursorDisplay.c_str(), fontResource);
283 }
284 cursorX = mRenderX + cursorWidth + scrollingX;
285 if (cursorX >= mRenderX + mRenderW) {
286 scrollingX = mRenderW - cursorWidth;
287 cursorX = mRenderX + mRenderW - CursorWidth;
288 } else if (cursorX < mRenderX) {
289 scrollingX = cursorWidth * -1;
290 cursorX = mRenderX;
291 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400292}
293
294int GUIInput::Render(void)
295{
296 if (!isConditionTrue())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200297 {
298 mRendered = false;
299 return 0;
300 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400301
302 void* fontResource = NULL;
303 if (mFont) fontResource = mFont->GetResource();
304
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200305 // First step, fill background
Dees_Troy51a0e822012-09-05 15:24:24 -0400306 gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
307 gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
308
309 // Next, render the background resource (if it exists)
310 if (mBackground && mBackground->GetResource())
311 {
312 mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
313 mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
314 gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
315 }
316
317 int ret = 0;
318
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200319 // Render the text
Ethan Yonkera5db7122016-03-14 15:47:09 -0500320 if (mInputText) {
321 mInputText->SetRenderPos(mRenderX + scrollingX, mFontY);
322 mInputText->SetText(displayValue);
323 gr_clip(mRenderX, mRenderY, mRenderW, mRenderH);
324 ret = mInputText->Render();
325 gr_noclip();
326 }
327 if (ret < 0)
328 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400329
330 if (HasInputFocus && DrawCursor) {
331 // Render the cursor
Dees_Troy51a0e822012-09-05 15:24:24 -0400332 gr_color(mCursorColor.red, mCursorColor.green, mCursorColor.blue, 255);
333 gr_fill(cursorX, mFontY, CursorWidth, mFontHeight);
334 }
335
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200336 mRendered = true;
337 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400338}
339
340int GUIInput::Update(void)
341{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200342 if (!isConditionTrue()) return (mRendered ? 2 : 0);
343 if (!mRendered) return 2;
Dees_Troy51a0e822012-09-05 15:24:24 -0400344
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200345 int ret = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400346
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200347 if (mInputText) ret = mInputText->Update();
348 if (ret < 0) return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400349
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200350 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400351}
352
353int GUIInput::GetSelection(int x, int y)
354{
355 if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH) return -1;
356 return (x - mRenderX);
357}
358
359int GUIInput::NotifyTouch(TOUCH_STATE state, int x, int y)
360{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200361 static int startSelection = -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400362 void* fontResource = NULL;
363
364 if (mFont) fontResource = mFont->GetResource();
365
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200366 if (!isConditionTrue())
367 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400368
369 if (!HasInputFocus) {
370 if (state != TOUCH_RELEASE)
371 return 0; // Only change focus if touch releases within the input box
372 if (GetSelection(x, y) >= 0) {
373 // When changing focus, we don't scroll or change the cursor location
374 PageManager::SetKeyBoardFocus(0);
that8834a0f2016-01-05 23:29:30 +0100375 PageManager::NotifyCharInput(0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400376 SetInputFocus(1);
377 DrawCursor = true;
378 mRendered = false;
379 }
380 } else {
381 switch (state) {
382 case TOUCH_HOLD:
383 case TOUCH_REPEAT:
384 break;
385 case TOUCH_START:
386 startSelection = GetSelection(x,y);
387 lastX = x;
388 DrawCursor = false;
389 mRendered = false;
390 break;
391
392 case TOUCH_DRAG:
393 // Check if we dragged out of the selection window
394 if (GetSelection(x, y) == -1) {
395 lastX = 0;
396 break;
397 }
398
399 DrawCursor = false;
400
401 // Provide some debounce on initial touches
402 if (startSelection != -1 && abs(x - lastX) < 6) {
403 break;
404 }
405
406 startSelection = -1;
407 if (lastX != x)
408 HandleTextLocation(x);
409 break;
410
411 case TOUCH_RELEASE:
412 // We've moved the cursor location
Dees_Troy51a0e822012-09-05 15:24:24 -0400413 mRendered = false;
414 DrawCursor = true;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500415 HandleCursorByTouch(x);
Dees_Troy51a0e822012-09-05 15:24:24 -0400416 break;
417 }
418 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200419 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400420}
421
Vojtech Bocek07220562014-02-08 02:05:33 +0100422int GUIInput::NotifyVarChange(const std::string& varName, const std::string& value)
Dees_Troy51a0e822012-09-05 15:24:24 -0400423{
Vojtech Bocek07220562014-02-08 02:05:33 +0100424 GUIObject::NotifyVarChange(varName, value);
425
Ethan Yonkera5db7122016-03-14 15:47:09 -0500426 if (varName == mVariable) {
427 if (!isLocalChange) {
428 UpdateTextWidth();
429 HandleTextLocation(TW_INPUT_NO_UPDATE);
430 } else
431 isLocalChange = false;
Dees_Troy51a0e822012-09-05 15:24:24 -0400432 return 0;
433 }
Ethan Yonkera5db7122016-03-14 15:47:09 -0500434 if (varName.empty()) {
435 UpdateTextWidth();
436 HandleTextLocation(TW_INPUT_NO_UPDATE);
437 HandleCursorByText();
438 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400439 return 0;
440}
441
that8834a0f2016-01-05 23:29:30 +0100442int GUIInput::NotifyKey(int key, bool down)
443{
444 if (!HasInputFocus || !down)
445 return 1;
446
that8834a0f2016-01-05 23:29:30 +0100447 switch (key)
448 {
449 case KEY_LEFT:
Ethan Yonkera5db7122016-03-14 15:47:09 -0500450 if (mCursorLocation == 0)
that8834a0f2016-01-05 23:29:30 +0100451 return 0; // we're already at the beginning
452 if (mCursorLocation == -1) {
Ethan Yonkera5db7122016-03-14 15:47:09 -0500453 if (displayValue.size() == 0) {
454 cursorX = mRenderX;
that8834a0f2016-01-05 23:29:30 +0100455 return 0;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500456 }
457 mCursorLocation = displayValue.size() - 1;
that8834a0f2016-01-05 23:29:30 +0100458 } else {
459 mCursorLocation--;
that8834a0f2016-01-05 23:29:30 +0100460 }
461 mRendered = false;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500462 HandleCursorByText();
that8834a0f2016-01-05 23:29:30 +0100463 return 0;
464
465 case KEY_RIGHT:
466 if (mCursorLocation == -1)
467 return 0; // we're already at the end
468 mCursorLocation++;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500469 if ((int)displayValue.size() <= mCursorLocation)
that8834a0f2016-01-05 23:29:30 +0100470 mCursorLocation = -1;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500471 HandleCursorByText();
that8834a0f2016-01-05 23:29:30 +0100472 mRendered = false;
473 return 0;
474
475 case KEY_HOME:
476 case KEY_UP:
Ethan Yonkera5db7122016-03-14 15:47:09 -0500477 if (displayValue.size() == 0)
that8834a0f2016-01-05 23:29:30 +0100478 return 0;
479 mCursorLocation = 0;
that8834a0f2016-01-05 23:29:30 +0100480 mRendered = false;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500481 cursorX = mRenderX;
that8834a0f2016-01-05 23:29:30 +0100482 return 0;
483
484 case KEY_END:
485 case KEY_DOWN:
486 mCursorLocation = -1;
487 mRendered = false;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500488 HandleCursorByText();
that8834a0f2016-01-05 23:29:30 +0100489 return 0;
490 }
491
492 return 1;
493}
494
495int GUIInput::NotifyCharInput(int key)
Dees_Troy51a0e822012-09-05 15:24:24 -0400496{
Dees_Troy51a0e822012-09-05 15:24:24 -0400497 if (HasInputFocus) {
498 if (key == KEYBOARD_BACKSPACE) {
499 //Backspace
Ethan Yonkera5db7122016-03-14 15:47:09 -0500500 if (displayValue.size() > 0 && mCursorLocation != 0) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400501 if (mCursorLocation == -1) {
Ethan Yonkera5db7122016-03-14 15:47:09 -0500502 displayValue.resize(displayValue.size() - 1);
Dees_Troy51a0e822012-09-05 15:24:24 -0400503 } else {
Ethan Yonkera5db7122016-03-14 15:47:09 -0500504 displayValue.erase(mCursorLocation - 1, 1);
505 mCursorLocation--;
Dees_Troy51a0e822012-09-05 15:24:24 -0400506 }
507 isLocalChange = true;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500508 DataManager::SetValue(mVariable, displayValue);
509 UpdateTextWidth();
510 HandleTextLocation(TW_INPUT_NO_UPDATE);
511 HandleCursorByText();
Dees_Troy51a0e822012-09-05 15:24:24 -0400512 }
513 } else if (key == KEYBOARD_SWIPE_LEFT) {
514 // Delete all
515 isLocalChange = true;
516 if (mCursorLocation == -1) {
517 DataManager::SetValue (mVariable, "");
Ethan Yonkera5db7122016-03-14 15:47:09 -0500518 displayValue = "";
519 textWidth = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400520 mCursorLocation = -1;
521 } else {
Ethan Yonkera5db7122016-03-14 15:47:09 -0500522 displayValue.erase(0, mCursorLocation);
523 DataManager::SetValue(mVariable, displayValue);
524 UpdateTextWidth();
Dees_Troy51a0e822012-09-05 15:24:24 -0400525 mCursorLocation = 0;
526 }
Ethan Yonkera5db7122016-03-14 15:47:09 -0500527 cursorX = mRenderX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400528 scrollingX = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400529 mRendered = false;
530 return 0;
that8834a0f2016-01-05 23:29:30 +0100531 } else if (key >= 32) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400532 // Regular key
533 if (HasAllowed && AllowedList.find((char)key) == string::npos) {
534 return 0;
535 }
536 if (HasDisabled && DisabledList.find((char)key) != string::npos) {
537 return 0;
538 }
Ethan Yonkera5db7122016-03-14 15:47:09 -0500539 if (MaxLen != 0 && displayValue.size() >= MaxLen) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400540 return 0;
541 }
542 if (mCursorLocation == -1) {
Ethan Yonkera5db7122016-03-14 15:47:09 -0500543 displayValue += key;
Dees_Troy51a0e822012-09-05 15:24:24 -0400544 } else {
Ethan Yonkera5db7122016-03-14 15:47:09 -0500545 displayValue.insert(mCursorLocation, 1, key);
Dees_Troy51a0e822012-09-05 15:24:24 -0400546 mCursorLocation++;
547 }
548 isLocalChange = true;
Ethan Yonkera5db7122016-03-14 15:47:09 -0500549 DataManager::SetValue(mVariable, displayValue);
550 UpdateTextWidth();
551 HandleTextLocation(TW_INPUT_NO_UPDATE);
552 HandleCursorByText();
Dees_Troy51a0e822012-09-05 15:24:24 -0400553 } else if (key == KEYBOARD_ACTION) {
554 // Action
Dees_Troy51a0e822012-09-05 15:24:24 -0400555 if (mAction) {
Ethan Yonkera5db7122016-03-14 15:47:09 -0500556 unsigned inputLen = displayValue.length();
Dees_Troy51a0e822012-09-05 15:24:24 -0400557 if (inputLen < MinLen)
558 return 0;
559 else if (MaxLen != 0 && inputLen > MaxLen)
560 return 0;
561 else
562 return (mAction ? mAction->NotifyTouch(TOUCH_RELEASE, mRenderX, mRenderY) : 1);
563 }
564 }
565 return 0;
566 } else {
567 if (key == 0) {
568 // Somewhat ugly hack-ish way to tell the box to redraw after losing focus to remove the cursor
569 mRendered = false;
570 return 1;
571 }
572 }
573 return 1;
574}