blob: c12ecc2b2dcada7d7465e56b2f067dd4c31d157c [file] [log] [blame]
Dees Troy3be70a82013-10-22 14:25:12 +00001/*
2 Copyright 2012 bigbiff/Dees_Troy TeamWin
3 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
49GUIInput::GUIInput(xml_node<>* node)
Vojtech Bocekede51c52014-02-07 23:58:09 +010050 : GUIObject(node)
Dees_Troy51a0e822012-09-05 15:24:24 -040051{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020052 xml_attribute<>* attr;
53 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -040054
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020055 mInputText = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040056 mAction = NULL;
57 mBackground = NULL;
58 mCursor = NULL;
59 mFont = NULL;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020060 mRendered = false;
Dees_Troy51a0e822012-09-05 15:24:24 -040061 HasMask = false;
62 DrawCursor = false;
63 isLocalChange = true;
64 HasAllowed = false;
65 HasDisabled = false;
66 skipChars = scrollingX = mFontHeight = mFontY = lastX = 0;
67 mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = MinLen = MaxLen = 0;
68 mCursorLocation = -1; // -1 is always the end of the string
69 CursorWidth = 3;
70 ConvertStrToColor("black", &mBackgroundColor);
71 ConvertStrToColor("white", &mCursorColor);
72
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020073 if (!node)
74 return;
Dees_Troy51a0e822012-09-05 15:24:24 -040075
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020076 // Load text directly from the node
77 mInputText = new GUIText(node);
Dees_Troy51a0e822012-09-05 15:24:24 -040078 // Load action directly from the node
79 mAction = new GUIAction(node);
80
81 if (mInputText->Render() < 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020082 {
83 delete mInputText;
84 mInputText = NULL;
85 }
Dees_Troy51a0e822012-09-05 15:24:24 -040086
87 // Load the background
Ethan Yonker21ff02a2015-02-18 14:35:00 -060088 child = FindNode(node, "background");
Dees_Troy51a0e822012-09-05 15:24:24 -040089 if (child)
90 {
thatf6ed8fc2015-02-14 20:23:16 +010091 mBackground = LoadAttrImage(child, "resource");
92 mBackgroundColor = LoadAttrColor(child, "color", mBackgroundColor);
Dees_Troy51a0e822012-09-05 15:24:24 -040093 }
94 if (mBackground && mBackground->GetResource())
95 {
thatf6ed8fc2015-02-14 20:23:16 +010096 mBackgroundW = mBackground->GetWidth();
97 mBackgroundH = mBackground->GetHeight();
Dees_Troy51a0e822012-09-05 15:24:24 -040098 }
99
100 // Load the cursor color
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600101 child = FindNode(node, "cursor");
Dees_Troy51a0e822012-09-05 15:24:24 -0400102 if (child)
103 {
thatf6ed8fc2015-02-14 20:23:16 +0100104 mCursor = LoadAttrImage(child, "resource");
105 mCursorColor = LoadAttrColor(child, "color", mCursorColor);
Dees_Troy51a0e822012-09-05 15:24:24 -0400106 attr = child->first_attribute("hasfocus");
107 if (attr)
108 {
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600109 std::string focus = attr->value();
110 SetInputFocus(atoi(focus.c_str()));
Dees_Troy51a0e822012-09-05 15:24:24 -0400111 }
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600112 CursorWidth = LoadAttrIntScaleX(child, "width", CursorWidth);
Dees_Troy51a0e822012-09-05 15:24:24 -0400113 }
114 DrawCursor = HasInputFocus;
115
thatf6ed8fc2015-02-14 20:23:16 +0100116 // Load the font
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600117 child = FindNode(node, "font");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200118 if (child)
119 {
thatf6ed8fc2015-02-14 20:23:16 +0100120 mFont = LoadAttrFont(child, "resource");
121 mFontHeight = mFont->GetHeight();
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200122 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400123
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600124 child = FindNode(node, "text");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200125 if (child) mText = child->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400126 mLastValue = gui_parse_text(mText);
127
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600128 child = FindNode(node, "data");
Dees_Troy51a0e822012-09-05 15:24:24 -0400129 if (child)
130 {
131 attr = child->first_attribute("name");
132 if (attr)
133 mVariable = attr->value();
134 attr = child->first_attribute("default");
135 if (attr)
136 DataManager::SetValue(mVariable, attr->value());
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600137 mMask = LoadAttrString(child, "mask");
138 HasMask = !mMask.empty();
Dees_Troy51a0e822012-09-05 15:24:24 -0400139 attr = child->first_attribute("maskvariable");
140 if (attr)
141 mMaskVariable = attr->value();
142 else
143 mMaskVariable = mVariable;
144 }
145
146 // Load input restrictions
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600147 child = FindNode(node, "restrict");
Dees_Troy51a0e822012-09-05 15:24:24 -0400148 if (child)
149 {
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600150 MinLen = LoadAttrInt(child, "minlen", MinLen);
151 MaxLen = LoadAttrInt(child, "maxlen", MaxLen);
152 AllowedList = LoadAttrString(child, "allow");
153 HasAllowed = !AllowedList.empty();
154 DisabledList = LoadAttrString(child, "disable");
155 HasDisabled = !DisabledList.empty();
Dees_Troy51a0e822012-09-05 15:24:24 -0400156 }
157
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200158 // Load the placement
Ethan Yonker21ff02a2015-02-18 14:35:00 -0600159 LoadPlacement(FindNode(node, "placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
Dees_Troy51a0e822012-09-05 15:24:24 -0400160 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
161
162 if (mInputText && mFontHeight && mFontHeight < (unsigned)mRenderH) {
163 mFontY = ((mRenderH - mFontHeight) / 2) + mRenderY;
164 mInputText->SetRenderPos(mRenderX, mFontY);
165 } else
166 mFontY = mRenderY;
167
168 if (mInputText)
169 mInputText->SetMaxWidth(mRenderW);
170
171 isLocalChange = false;
172 HandleTextLocation(-3);
Dees_Troy51a0e822012-09-05 15:24:24 -0400173}
174
175GUIInput::~GUIInput()
176{
thatf6ed8fc2015-02-14 20:23:16 +0100177 delete mInputText;
178 delete mAction;
Dees_Troy51a0e822012-09-05 15:24:24 -0400179}
180
181int GUIInput::HandleTextLocation(int x)
182{
183 int textWidth;
184 string displayValue, originalValue, insertChar;
185 void* fontResource = NULL;
186
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200187 if (mFont)
188 fontResource = mFont->GetResource();
Dees_Troy51a0e822012-09-05 15:24:24 -0400189
190 DataManager::GetValue(mVariable, originalValue);
191 displayValue = originalValue;
192 if (HasMask) {
193 int index, string_size = displayValue.size();
194 string maskedValue;
195 for (index=0; index<string_size; index++)
196 maskedValue += mMask;
197 displayValue = maskedValue;
198 }
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100199 textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400200 if (textWidth <= mRenderW) {
201 lastX = x;
202 scrollingX = 0;
203 skipChars = 0;
204 mInputText->SkipCharCount(skipChars);
205 mRendered = false;
206 return 0;
207 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200208
209 if (skipChars && skipChars < displayValue.size())
Dees_Troy51a0e822012-09-05 15:24:24 -0400210 displayValue.erase(0, skipChars);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200211
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100212 textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400213 mRendered = false;
214
215 int deltaX, deltaText, newWidth;
216
217 if (x < -1000) {
218 // No change in scrolling
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200219 if (x == -1003)
Dees_Troy51a0e822012-09-05 15:24:24 -0400220 mCursorLocation = -1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200221
Dees_Troy51a0e822012-09-05 15:24:24 -0400222 if (mCursorLocation == -1) {
223 displayValue = originalValue;
224 skipChars = 0;
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100225 textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400226 while (textWidth > mRenderW) {
227 displayValue.erase(0, 1);
228 skipChars++;
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100229 textWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400230 }
231 scrollingX = mRenderW - textWidth;
232 mInputText->SkipCharCount(skipChars);
233 } else if (x == -1001) {
234 // Added a new character
235 int adjust_scrollingX = 0;
236 string cursorLocate;
237
238 cursorLocate = displayValue;
239 cursorLocate.resize(mCursorLocation);
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100240 textWidth = gr_ttf_measureEx(cursorLocate.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400241 while (textWidth > mRenderW) {
242 skipChars++;
243 mCursorLocation--;
244 cursorLocate.erase(0, 1);
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100245 textWidth = gr_ttf_measureEx(cursorLocate.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400246 adjust_scrollingX = -1;
247 }
248 if (adjust_scrollingX) {
249 scrollingX = mRenderW - textWidth;
250 if (scrollingX < 0)
251 scrollingX = 0;
252 }
253 mInputText->SkipCharCount(skipChars);
254 } else if (x == -1002) {
255 // Deleted a character
256 while (-1) {
257 if (skipChars == 0) {
258 scrollingX = 0;
259 mInputText->SkipCharCount(skipChars);
260 return 0;
261 }
262 insertChar = originalValue.substr(skipChars - 1, 1);
263 displayValue.insert(0, insertChar);
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100264 newWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400265 deltaText = newWidth - textWidth;
266 if (newWidth > mRenderW) {
267 scrollingX = mRenderW - textWidth;
268 if (scrollingX < 0)
269 scrollingX = 0;
270 mInputText->SkipCharCount(skipChars);
271 return 0;
272 } else {
273 textWidth = newWidth;
274 skipChars--;
275 mCursorLocation++;
276 }
277 }
278 } else
Dees_Troy2673cec2013-04-02 20:22:16 +0000279 LOGINFO("GUIInput::HandleTextLocation -> We really shouldn't ever get here...\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400280 } else if (x > lastX) {
281 // Dragging to right, scrolling left
282 while (-1) {
283 deltaX = x - lastX + scrollingX;
284 if (skipChars == 0 || deltaX == 0) {
285 scrollingX = 0;
286 lastX = x;
287 mInputText->SkipCharCount(skipChars);
288 return 0;
289 }
290 insertChar = originalValue.substr(skipChars - 1, 1);
291 displayValue.insert(0, insertChar);
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100292 newWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400293 deltaText = newWidth - textWidth;
294 if (deltaText < deltaX) {
295 lastX += deltaText;
296 textWidth = newWidth;
297 skipChars--;
298 } else {
299 scrollingX = deltaX;
300 lastX = x;
301 mInputText->SkipCharCount(skipChars);
302 return 0;
303 }
304 }
305 } else if (x < lastX) {
306 // Dragging to left, scrolling right
307 if (textWidth <= mRenderW) {
308 lastX = x;
309 scrollingX = mRenderW - textWidth;
310 return 0;
311 }
312 if (scrollingX) {
313 deltaX = lastX - x;
314 if (scrollingX > deltaX) {
315 scrollingX -= deltaX;
316 lastX = x;
317 return 0;
318 } else {
319 lastX -= deltaX;
320 scrollingX = 0;
321 }
322 }
323 while (-1) {
324 deltaX = lastX - x;
325 displayValue.erase(0, 1);
326 skipChars++;
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100327 newWidth = gr_ttf_measureEx(displayValue.c_str(), fontResource);
Dees_Troy51a0e822012-09-05 15:24:24 -0400328 deltaText = textWidth - newWidth;
329 if (newWidth <= mRenderW) {
330 scrollingX = mRenderW - newWidth;
331 lastX = x;
332 mInputText->SkipCharCount(skipChars);
333 return 0;
334 }
335 if (deltaText < deltaX) {
336 lastX -= deltaText;
337 textWidth = newWidth;
338 } else {
339 scrollingX = deltaText - deltaX;
340 lastX = x;
341 mInputText->SkipCharCount(skipChars);
342 return 0;
343 }
344 }
345 }
346 return 0;
347}
348
349int GUIInput::Render(void)
350{
351 if (!isConditionTrue())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200352 {
353 mRendered = false;
354 return 0;
355 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400356
357 void* fontResource = NULL;
358 if (mFont) fontResource = mFont->GetResource();
359
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200360 // First step, fill background
Dees_Troy51a0e822012-09-05 15:24:24 -0400361 gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
362 gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
363
364 // Next, render the background resource (if it exists)
365 if (mBackground && mBackground->GetResource())
366 {
367 mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
368 mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
369 gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
370 }
371
372 int ret = 0;
373
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200374 // Render the text
Dees_Troy51a0e822012-09-05 15:24:24 -0400375 mInputText->SetRenderPos(mRenderX + scrollingX, mFontY);
376 mInputText->SetMaxWidth(mRenderW - scrollingX);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200377 if (mInputText) ret = mInputText->Render();
378 if (ret < 0) return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400379
380 if (HasInputFocus && DrawCursor) {
381 // Render the cursor
382 string displayValue;
383 int cursorX;
384 DataManager::GetValue(mVariable, displayValue);
385 if (HasMask) {
386 int index, string_size = displayValue.size();
387 string maskedValue;
388 for (index=0; index<string_size; index++)
389 maskedValue += mMask;
390 displayValue = maskedValue;
391 }
392 if (displayValue.size() == 0) {
393 skipChars = 0;
394 mCursorLocation = -1;
395 cursorX = mRenderX;
396 } else {
397 if (skipChars && skipChars < displayValue.size()) {
398 displayValue.erase(0, skipChars);
399 }
400 if (mCursorLocation == 0) {
401 // Cursor is at the beginning
402 cursorX = mRenderX;
403 } else if (mCursorLocation > 0) {
404 // Cursor is in the middle
405 if (displayValue.size() > (unsigned)mCursorLocation) {
406 string cursorDisplay;
407
408 cursorDisplay = displayValue;
409 cursorDisplay.resize(mCursorLocation);
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100410 cursorX = gr_ttf_measureEx(cursorDisplay.c_str(), fontResource) + mRenderX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400411 } else {
412 // Cursor location is after the end of the text - reset to -1
413 mCursorLocation = -1;
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100414 cursorX = gr_ttf_measureEx(displayValue.c_str(), fontResource) + mRenderX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400415 }
416 } else {
417 // Cursor is at the end (-1)
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100418 cursorX = gr_ttf_measureEx(displayValue.c_str(), fontResource) + mRenderX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400419 }
420 }
421 cursorX += scrollingX;
422 // Make sure that the cursor doesn't go past the boundaries of the box
423 if (cursorX + (int)CursorWidth > mRenderX + mRenderW)
424 cursorX = mRenderX + mRenderW - CursorWidth;
425
426 // Set the color for the cursor
427 gr_color(mCursorColor.red, mCursorColor.green, mCursorColor.blue, 255);
428 gr_fill(cursorX, mFontY, CursorWidth, mFontHeight);
429 }
430
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200431 mRendered = true;
432 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400433}
434
435int GUIInput::Update(void)
436{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200437 if (!isConditionTrue()) return (mRendered ? 2 : 0);
438 if (!mRendered) return 2;
Dees_Troy51a0e822012-09-05 15:24:24 -0400439
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200440 int ret = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400441
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200442 if (mInputText) ret = mInputText->Update();
443 if (ret < 0) return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400444
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200445 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400446}
447
448int GUIInput::GetSelection(int x, int y)
449{
450 if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH) return -1;
451 return (x - mRenderX);
452}
453
454int GUIInput::NotifyTouch(TOUCH_STATE state, int x, int y)
455{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200456 static int startSelection = -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400457 int textWidth;
458 string displayValue, originalValue;
459 void* fontResource = NULL;
460
461 if (mFont) fontResource = mFont->GetResource();
462
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200463 if (!isConditionTrue())
464 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400465
466 if (!HasInputFocus) {
467 if (state != TOUCH_RELEASE)
468 return 0; // Only change focus if touch releases within the input box
469 if (GetSelection(x, y) >= 0) {
470 // When changing focus, we don't scroll or change the cursor location
471 PageManager::SetKeyBoardFocus(0);
that8834a0f2016-01-05 23:29:30 +0100472 PageManager::NotifyCharInput(0);
Dees_Troy51a0e822012-09-05 15:24:24 -0400473 SetInputFocus(1);
474 DrawCursor = true;
475 mRendered = false;
476 }
477 } else {
478 switch (state) {
479 case TOUCH_HOLD:
480 case TOUCH_REPEAT:
481 break;
482 case TOUCH_START:
483 startSelection = GetSelection(x,y);
484 lastX = x;
485 DrawCursor = false;
486 mRendered = false;
487 break;
488
489 case TOUCH_DRAG:
490 // Check if we dragged out of the selection window
491 if (GetSelection(x, y) == -1) {
492 lastX = 0;
493 break;
494 }
495
496 DrawCursor = false;
497
498 // Provide some debounce on initial touches
499 if (startSelection != -1 && abs(x - lastX) < 6) {
500 break;
501 }
502
503 startSelection = -1;
504 if (lastX != x)
505 HandleTextLocation(x);
506 break;
507
508 case TOUCH_RELEASE:
509 // We've moved the cursor location
510 int relativeX = x - mRenderX;
511
512 mRendered = false;
513 DrawCursor = true;
514 DataManager::GetValue(mVariable, displayValue);
515 if (HasMask) {
516 int index, string_size = displayValue.size();
517 string maskedValue;
518 for (index=0; index<string_size; index++)
519 maskedValue += mMask;
520 displayValue = maskedValue;
521 }
522 if (displayValue.size() == 0) {
523 skipChars = 0;
524 mCursorLocation = -1;
525 return 0;
526 } else if (skipChars && skipChars < displayValue.size()) {
527 displayValue.erase(0, skipChars);
528 }
529
530 string cursorString;
531 int cursorX = 0;
532 unsigned index = 0;
533
534 for(index=0; index<displayValue.size(); index++)
535 {
536 cursorString = displayValue.substr(0, index);
Ethan Yonkerfbb43532015-12-28 21:54:50 +0100537 cursorX = gr_ttf_measureEx(cursorString.c_str(), fontResource) + mRenderX;
Dees_Troy51a0e822012-09-05 15:24:24 -0400538 if (cursorX > x) {
539 if (index > 0)
540 mCursorLocation = index - 1;
541 else
542 mCursorLocation = index;
543 return 0;
544 }
545 }
546 mCursorLocation = -1;
547 break;
548 }
549 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200550 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400551}
552
Vojtech Bocek07220562014-02-08 02:05:33 +0100553int GUIInput::NotifyVarChange(const std::string& varName, const std::string& value)
Dees_Troy51a0e822012-09-05 15:24:24 -0400554{
Vojtech Bocek07220562014-02-08 02:05:33 +0100555 GUIObject::NotifyVarChange(varName, value);
556
Dees_Troy51a0e822012-09-05 15:24:24 -0400557 if (varName == mVariable && !isLocalChange) {
558 HandleTextLocation(-1003);
559 return 0;
560 }
561 return 0;
562}
563
that8834a0f2016-01-05 23:29:30 +0100564int GUIInput::NotifyKey(int key, bool down)
565{
566 if (!HasInputFocus || !down)
567 return 1;
568
569 string variableValue;
570 switch (key)
571 {
572 case KEY_LEFT:
573 if (mCursorLocation == 0 && skipChars == 0)
574 return 0; // we're already at the beginning
575 if (mCursorLocation == -1) {
576 DataManager::GetValue(mVariable, variableValue);
577 if (variableValue.size() == 0)
578 return 0;
579 mCursorLocation = variableValue.size() - skipChars - 1;
580 } else if (mCursorLocation == 0) {
581 skipChars--;
582 HandleTextLocation(-1002);
583 } else {
584 mCursorLocation--;
585 HandleTextLocation(-1002);
586 }
587 mRendered = false;
588 return 0;
589
590 case KEY_RIGHT:
591 if (mCursorLocation == -1)
592 return 0; // we're already at the end
593 mCursorLocation++;
594 DataManager::GetValue(mVariable, variableValue);
595 if (variableValue.size() <= mCursorLocation + skipChars)
596 mCursorLocation = -1;
597 HandleTextLocation(-1001);
598 mRendered = false;
599 return 0;
600
601 case KEY_HOME:
602 case KEY_UP:
603 DataManager::GetValue(mVariable, variableValue);
604 if (variableValue.size() == 0)
605 return 0;
606 mCursorLocation = 0;
607 skipChars = 0;
608 mRendered = false;
609 HandleTextLocation(-1002);
610 return 0;
611
612 case KEY_END:
613 case KEY_DOWN:
614 mCursorLocation = -1;
615 mRendered = false;
616 HandleTextLocation(-1003);
617 return 0;
618 }
619
620 return 1;
621}
622
623int GUIInput::NotifyCharInput(int key)
Dees_Troy51a0e822012-09-05 15:24:24 -0400624{
625 string variableValue;
626
627 if (HasInputFocus) {
628 if (key == KEYBOARD_BACKSPACE) {
629 //Backspace
630 DataManager::GetValue(mVariable, variableValue);
631 if (variableValue.size() > 0 && (mCursorLocation + skipChars != 0 || mCursorLocation == -1)) {
632 if (mCursorLocation == -1) {
633 variableValue.resize(variableValue.size() - 1);
634 } else {
635 variableValue.erase(mCursorLocation + skipChars - 1, 1);
636 if (mCursorLocation > 0)
637 mCursorLocation--;
638 else if (skipChars > 0)
639 skipChars--;
640 }
641 isLocalChange = true;
642 DataManager::SetValue(mVariable, variableValue);
643 isLocalChange = false;
644
645 if (HasMask) {
646 int index, string_size = variableValue.size();
647 string maskedValue;
648 for (index=0; index<string_size; index++)
649 maskedValue += mMask;
650 DataManager::SetValue(mMaskVariable, maskedValue);
651 }
652 HandleTextLocation(-1002);
653 }
654 } else if (key == KEYBOARD_SWIPE_LEFT) {
655 // Delete all
656 isLocalChange = true;
657 if (mCursorLocation == -1) {
658 DataManager::SetValue (mVariable, "");
659 if (HasMask)
660 DataManager::SetValue(mMaskVariable, "");
661 mCursorLocation = -1;
662 } else {
663 DataManager::GetValue(mVariable, variableValue);
664 variableValue.erase(0, mCursorLocation + skipChars);
665 DataManager::SetValue(mVariable, variableValue);
666 if (HasMask) {
667 DataManager::GetValue(mMaskVariable, variableValue);
668 variableValue.erase(0, mCursorLocation + skipChars);
669 DataManager::SetValue(mMaskVariable, variableValue);
670 }
671 mCursorLocation = 0;
672 }
673 skipChars = 0;
674 scrollingX = 0;
675 mInputText->SkipCharCount(skipChars);
676 isLocalChange = false;
677 mRendered = false;
678 return 0;
that8834a0f2016-01-05 23:29:30 +0100679 } else if (key >= 32) {
Dees_Troy51a0e822012-09-05 15:24:24 -0400680 // Regular key
681 if (HasAllowed && AllowedList.find((char)key) == string::npos) {
682 return 0;
683 }
684 if (HasDisabled && DisabledList.find((char)key) != string::npos) {
685 return 0;
686 }
687 DataManager::GetValue(mVariable, variableValue);
688 if (MaxLen != 0 && variableValue.size() >= MaxLen) {
689 return 0;
690 }
691 if (mCursorLocation == -1) {
692 variableValue += key;
693 } else {
that5fa54ce2015-02-01 16:15:29 +0100694 variableValue.insert(mCursorLocation + skipChars, 1, key);
Dees_Troy51a0e822012-09-05 15:24:24 -0400695 mCursorLocation++;
696 }
697 isLocalChange = true;
698 DataManager::SetValue(mVariable, variableValue);
699 HandleTextLocation(-1001);
700 isLocalChange = false;
701
702 if (HasMask) {
703 int index, string_size = variableValue.size();
704 string maskedValue;
705 for (index=0; index<string_size; index++)
706 maskedValue += mMask;
707 DataManager::SetValue(mMaskVariable, maskedValue);
708 }
709 } else if (key == KEYBOARD_ACTION) {
710 // Action
711 DataManager::GetValue(mVariable, variableValue);
712 if (mAction) {
713 unsigned inputLen = variableValue.length();
714 if (inputLen < MinLen)
715 return 0;
716 else if (MaxLen != 0 && inputLen > MaxLen)
717 return 0;
718 else
719 return (mAction ? mAction->NotifyTouch(TOUCH_RELEASE, mRenderX, mRenderY) : 1);
720 }
721 }
722 return 0;
723 } else {
724 if (key == 0) {
725 // Somewhat ugly hack-ish way to tell the box to redraw after losing focus to remove the cursor
726 mRendered = false;
727 return 1;
728 }
729 }
730 return 1;
731}