blob: 19e4e6a5b4110bc0922319b01a7508fe44c76814 [file] [log] [blame]
Dees_Troy51a0e822012-09-05 15:24:24 -04001// input.cpp - GUIInput object
2
3#include <linux/input.h>
4#include <pthread.h>
5#include <stdarg.h>
6#include <stdio.h>
7#include <stdlib.h>
8#include <string.h>
9#include <fcntl.h>
10#include <sys/reboot.h>
11#include <sys/stat.h>
12#include <sys/time.h>
13#include <sys/mman.h>
14#include <sys/types.h>
15#include <sys/ioctl.h>
16#include <time.h>
17#include <unistd.h>
18#include <stdlib.h>
19
20#include <string>
21
22extern "C" {
Dees_Troy2673cec2013-04-02 20:22:16 +000023#include "../twcommon.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040024#include "../minuitwrp/minui.h"
Dees_Troy51a0e822012-09-05 15:24:24 -040025}
26
27#include "rapidxml.hpp"
28#include "objects.hpp"
29#include "../data.hpp"
30
31GUIInput::GUIInput(xml_node<>* node)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020032 : Conditional(node)
Dees_Troy51a0e822012-09-05 15:24:24 -040033{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020034 xml_attribute<>* attr;
35 xml_node<>* child;
Dees_Troy51a0e822012-09-05 15:24:24 -040036
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020037 mInputText = NULL;
Dees_Troy51a0e822012-09-05 15:24:24 -040038 mAction = NULL;
39 mBackground = NULL;
40 mCursor = NULL;
41 mFont = NULL;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020042 mRendered = false;
Dees_Troy51a0e822012-09-05 15:24:24 -040043 HasMask = false;
44 DrawCursor = false;
45 isLocalChange = true;
46 HasAllowed = false;
47 HasDisabled = false;
48 skipChars = scrollingX = mFontHeight = mFontY = lastX = 0;
49 mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = MinLen = MaxLen = 0;
50 mCursorLocation = -1; // -1 is always the end of the string
51 CursorWidth = 3;
52 ConvertStrToColor("black", &mBackgroundColor);
53 ConvertStrToColor("white", &mCursorColor);
54
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020055 if (!node)
56 return;
Dees_Troy51a0e822012-09-05 15:24:24 -040057
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020058 // Load text directly from the node
59 mInputText = new GUIText(node);
Dees_Troy51a0e822012-09-05 15:24:24 -040060 // Load action directly from the node
61 mAction = new GUIAction(node);
62
63 if (mInputText->Render() < 0)
Vojtech Bocekfafb0c52013-07-25 22:53:02 +020064 {
65 delete mInputText;
66 mInputText = NULL;
67 }
Dees_Troy51a0e822012-09-05 15:24:24 -040068
69 // Load the background
70 child = node->first_node("background");
71 if (child)
72 {
73 attr = child->first_attribute("resource");
74 if (attr)
75 mBackground = PageManager::FindResource(attr->value());
76 attr = child->first_attribute("color");
77 if (attr)
78 {
79 std::string color = attr->value();
80 ConvertStrToColor(color, &mBackgroundColor);
81 }
82 }
83 if (mBackground && mBackground->GetResource())
84 {
85 mBackgroundW = gr_get_width(mBackground->GetResource());
86 mBackgroundH = gr_get_height(mBackground->GetResource());
87 }
88
89 // Load the cursor color
90 child = node->first_node("cursor");
91 if (child)
92 {
93 attr = child->first_attribute("resource");
94 if (attr)
95 mCursor = PageManager::FindResource(attr->value());
96 attr = child->first_attribute("color");
97 if (attr)
98 {
99 std::string color = attr->value();
100 ConvertStrToColor(color, &mCursorColor);
101 }
102 attr = child->first_attribute("hasfocus");
103 if (attr)
104 {
105 std::string color = attr->value();
106 SetInputFocus(atoi(color.c_str()));
107 }
108 attr = child->first_attribute("width");
109 if (attr)
110 {
111 std::string cwidth = gui_parse_text(attr->value());
112 CursorWidth = atoi(cwidth.c_str());
113 }
114 }
115 DrawCursor = HasInputFocus;
116
117 // Load the font, and possibly override the color
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200118 child = node->first_node("font");
119 if (child)
120 {
121 attr = child->first_attribute("resource");
122 if (attr) {
123 mFont = PageManager::FindResource(attr->value());
Dees_Troy51a0e822012-09-05 15:24:24 -0400124 gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
125 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200126 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400127
128 child = node->first_node("text");
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200129 if (child) mText = child->value();
Dees_Troy51a0e822012-09-05 15:24:24 -0400130 mLastValue = gui_parse_text(mText);
131
132 child = node->first_node("data");
133 if (child)
134 {
135 attr = child->first_attribute("name");
136 if (attr)
137 mVariable = attr->value();
138 attr = child->first_attribute("default");
139 if (attr)
140 DataManager::SetValue(mVariable, attr->value());
141 attr = child->first_attribute("mask");
142 if (attr) {
143 mMask = attr->value();
144 HasMask = true;
145 }
146 attr = child->first_attribute("maskvariable");
147 if (attr)
148 mMaskVariable = attr->value();
149 else
150 mMaskVariable = mVariable;
151 }
152
153 // Load input restrictions
154 child = node->first_node("restrict");
155 if (child)
156 {
157 attr = child->first_attribute("minlen");
158 if (attr) {
159 std::string attrib = attr->value();
160 MinLen = atoi(attrib.c_str());
161 }
162 attr = child->first_attribute("maxlen");
163 if (attr) {
164 std::string attrib = attr->value();
165 MaxLen = atoi(attrib.c_str());
166 }
167 attr = child->first_attribute("allow");
168 if (attr) {
169 HasAllowed = true;
170 AllowedList = attr->value();
171 }
172 attr = child->first_attribute("disable");
173 if (attr) {
174 HasDisabled = true;
175 DisabledList = attr->value();
176 }
177 }
178
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200179 // Load the placement
Dees_Troy51a0e822012-09-05 15:24:24 -0400180 LoadPlacement(node->first_node("placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
181 SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
182
183 if (mInputText && mFontHeight && mFontHeight < (unsigned)mRenderH) {
184 mFontY = ((mRenderH - mFontHeight) / 2) + mRenderY;
185 mInputText->SetRenderPos(mRenderX, mFontY);
186 } else
187 mFontY = mRenderY;
188
189 if (mInputText)
190 mInputText->SetMaxWidth(mRenderW);
191
192 isLocalChange = false;
193 HandleTextLocation(-3);
Dees_Troy51a0e822012-09-05 15:24:24 -0400194}
195
196GUIInput::~GUIInput()
197{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200198 if (mInputText) delete mInputText;
199 if (mBackground) delete mBackground;
200 if (mCursor) delete mCursor;
201 if (mFont) delete mFont;
202 if (mAction) delete mAction;
Dees_Troy51a0e822012-09-05 15:24:24 -0400203}
204
205int GUIInput::HandleTextLocation(int x)
206{
207 int textWidth;
208 string displayValue, originalValue, insertChar;
209 void* fontResource = NULL;
210
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200211 if (mFont)
212 fontResource = mFont->GetResource();
Dees_Troy51a0e822012-09-05 15:24:24 -0400213
214 DataManager::GetValue(mVariable, originalValue);
215 displayValue = originalValue;
216 if (HasMask) {
217 int index, string_size = displayValue.size();
218 string maskedValue;
219 for (index=0; index<string_size; index++)
220 maskedValue += mMask;
221 displayValue = maskedValue;
222 }
223 textWidth = gr_measureEx(displayValue.c_str(), fontResource);
224 if (textWidth <= mRenderW) {
225 lastX = x;
226 scrollingX = 0;
227 skipChars = 0;
228 mInputText->SkipCharCount(skipChars);
229 mRendered = false;
230 return 0;
231 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200232
233 if (skipChars && skipChars < displayValue.size())
Dees_Troy51a0e822012-09-05 15:24:24 -0400234 displayValue.erase(0, skipChars);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200235
Dees_Troy51a0e822012-09-05 15:24:24 -0400236 textWidth = gr_measureEx(displayValue.c_str(), fontResource);
237 mRendered = false;
238
239 int deltaX, deltaText, newWidth;
240
241 if (x < -1000) {
242 // No change in scrolling
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200243 if (x == -1003)
Dees_Troy51a0e822012-09-05 15:24:24 -0400244 mCursorLocation = -1;
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200245
Dees_Troy51a0e822012-09-05 15:24:24 -0400246 if (mCursorLocation == -1) {
247 displayValue = originalValue;
248 skipChars = 0;
249 textWidth = gr_measureEx(displayValue.c_str(), fontResource);
250 while (textWidth > mRenderW) {
251 displayValue.erase(0, 1);
252 skipChars++;
253 textWidth = gr_measureEx(displayValue.c_str(), fontResource);
254 }
255 scrollingX = mRenderW - textWidth;
256 mInputText->SkipCharCount(skipChars);
257 } else if (x == -1001) {
258 // Added a new character
259 int adjust_scrollingX = 0;
260 string cursorLocate;
261
262 cursorLocate = displayValue;
263 cursorLocate.resize(mCursorLocation);
264 textWidth = gr_measureEx(cursorLocate.c_str(), fontResource);
265 while (textWidth > mRenderW) {
266 skipChars++;
267 mCursorLocation--;
268 cursorLocate.erase(0, 1);
269 textWidth = gr_measureEx(cursorLocate.c_str(), fontResource);
270 adjust_scrollingX = -1;
271 }
272 if (adjust_scrollingX) {
273 scrollingX = mRenderW - textWidth;
274 if (scrollingX < 0)
275 scrollingX = 0;
276 }
277 mInputText->SkipCharCount(skipChars);
278 } else if (x == -1002) {
279 // Deleted a character
280 while (-1) {
281 if (skipChars == 0) {
282 scrollingX = 0;
283 mInputText->SkipCharCount(skipChars);
284 return 0;
285 }
286 insertChar = originalValue.substr(skipChars - 1, 1);
287 displayValue.insert(0, insertChar);
288 newWidth = gr_measureEx(displayValue.c_str(), fontResource);
289 deltaText = newWidth - textWidth;
290 if (newWidth > mRenderW) {
291 scrollingX = mRenderW - textWidth;
292 if (scrollingX < 0)
293 scrollingX = 0;
294 mInputText->SkipCharCount(skipChars);
295 return 0;
296 } else {
297 textWidth = newWidth;
298 skipChars--;
299 mCursorLocation++;
300 }
301 }
302 } else
Dees_Troy2673cec2013-04-02 20:22:16 +0000303 LOGINFO("GUIInput::HandleTextLocation -> We really shouldn't ever get here...\n");
Dees_Troy51a0e822012-09-05 15:24:24 -0400304 } else if (x > lastX) {
305 // Dragging to right, scrolling left
306 while (-1) {
307 deltaX = x - lastX + scrollingX;
308 if (skipChars == 0 || deltaX == 0) {
309 scrollingX = 0;
310 lastX = x;
311 mInputText->SkipCharCount(skipChars);
312 return 0;
313 }
314 insertChar = originalValue.substr(skipChars - 1, 1);
315 displayValue.insert(0, insertChar);
316 newWidth = gr_measureEx(displayValue.c_str(), fontResource);
317 deltaText = newWidth - textWidth;
318 if (deltaText < deltaX) {
319 lastX += deltaText;
320 textWidth = newWidth;
321 skipChars--;
322 } else {
323 scrollingX = deltaX;
324 lastX = x;
325 mInputText->SkipCharCount(skipChars);
326 return 0;
327 }
328 }
329 } else if (x < lastX) {
330 // Dragging to left, scrolling right
331 if (textWidth <= mRenderW) {
332 lastX = x;
333 scrollingX = mRenderW - textWidth;
334 return 0;
335 }
336 if (scrollingX) {
337 deltaX = lastX - x;
338 if (scrollingX > deltaX) {
339 scrollingX -= deltaX;
340 lastX = x;
341 return 0;
342 } else {
343 lastX -= deltaX;
344 scrollingX = 0;
345 }
346 }
347 while (-1) {
348 deltaX = lastX - x;
349 displayValue.erase(0, 1);
350 skipChars++;
351 newWidth = gr_measureEx(displayValue.c_str(), fontResource);
352 deltaText = textWidth - newWidth;
353 if (newWidth <= mRenderW) {
354 scrollingX = mRenderW - newWidth;
355 lastX = x;
356 mInputText->SkipCharCount(skipChars);
357 return 0;
358 }
359 if (deltaText < deltaX) {
360 lastX -= deltaText;
361 textWidth = newWidth;
362 } else {
363 scrollingX = deltaText - deltaX;
364 lastX = x;
365 mInputText->SkipCharCount(skipChars);
366 return 0;
367 }
368 }
369 }
370 return 0;
371}
372
373int GUIInput::Render(void)
374{
375 if (!isConditionTrue())
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200376 {
377 mRendered = false;
378 return 0;
379 }
Dees_Troy51a0e822012-09-05 15:24:24 -0400380
381 void* fontResource = NULL;
382 if (mFont) fontResource = mFont->GetResource();
383
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200384 // First step, fill background
Dees_Troy51a0e822012-09-05 15:24:24 -0400385 gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
386 gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
387
388 // Next, render the background resource (if it exists)
389 if (mBackground && mBackground->GetResource())
390 {
391 mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
392 mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
393 gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
394 }
395
396 int ret = 0;
397
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200398 // Render the text
Dees_Troy51a0e822012-09-05 15:24:24 -0400399 mInputText->SetRenderPos(mRenderX + scrollingX, mFontY);
400 mInputText->SetMaxWidth(mRenderW - scrollingX);
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200401 if (mInputText) ret = mInputText->Render();
402 if (ret < 0) return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400403
404 if (HasInputFocus && DrawCursor) {
405 // Render the cursor
406 string displayValue;
407 int cursorX;
408 DataManager::GetValue(mVariable, displayValue);
409 if (HasMask) {
410 int index, string_size = displayValue.size();
411 string maskedValue;
412 for (index=0; index<string_size; index++)
413 maskedValue += mMask;
414 displayValue = maskedValue;
415 }
416 if (displayValue.size() == 0) {
417 skipChars = 0;
418 mCursorLocation = -1;
419 cursorX = mRenderX;
420 } else {
421 if (skipChars && skipChars < displayValue.size()) {
422 displayValue.erase(0, skipChars);
423 }
424 if (mCursorLocation == 0) {
425 // Cursor is at the beginning
426 cursorX = mRenderX;
427 } else if (mCursorLocation > 0) {
428 // Cursor is in the middle
429 if (displayValue.size() > (unsigned)mCursorLocation) {
430 string cursorDisplay;
431
432 cursorDisplay = displayValue;
433 cursorDisplay.resize(mCursorLocation);
434 cursorX = gr_measureEx(cursorDisplay.c_str(), fontResource) + mRenderX;
435 } else {
436 // Cursor location is after the end of the text - reset to -1
437 mCursorLocation = -1;
438 cursorX = gr_measureEx(displayValue.c_str(), fontResource) + mRenderX;
439 }
440 } else {
441 // Cursor is at the end (-1)
442 cursorX = gr_measureEx(displayValue.c_str(), fontResource) + mRenderX;
443 }
444 }
445 cursorX += scrollingX;
446 // Make sure that the cursor doesn't go past the boundaries of the box
447 if (cursorX + (int)CursorWidth > mRenderX + mRenderW)
448 cursorX = mRenderX + mRenderW - CursorWidth;
449
450 // Set the color for the cursor
451 gr_color(mCursorColor.red, mCursorColor.green, mCursorColor.blue, 255);
452 gr_fill(cursorX, mFontY, CursorWidth, mFontHeight);
453 }
454
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200455 mRendered = true;
456 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400457}
458
459int GUIInput::Update(void)
460{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200461 if (!isConditionTrue()) return (mRendered ? 2 : 0);
462 if (!mRendered) return 2;
Dees_Troy51a0e822012-09-05 15:24:24 -0400463
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200464 int ret = 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400465
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200466 if (mInputText) ret = mInputText->Update();
467 if (ret < 0) return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400468
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200469 return ret;
Dees_Troy51a0e822012-09-05 15:24:24 -0400470}
471
472int GUIInput::GetSelection(int x, int y)
473{
474 if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH) return -1;
475 return (x - mRenderX);
476}
477
478int GUIInput::NotifyTouch(TOUCH_STATE state, int x, int y)
479{
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200480 static int startSelection = -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400481 int textWidth;
482 string displayValue, originalValue;
483 void* fontResource = NULL;
484
485 if (mFont) fontResource = mFont->GetResource();
486
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200487 if (!isConditionTrue())
488 return -1;
Dees_Troy51a0e822012-09-05 15:24:24 -0400489
490 if (!HasInputFocus) {
491 if (state != TOUCH_RELEASE)
492 return 0; // Only change focus if touch releases within the input box
493 if (GetSelection(x, y) >= 0) {
494 // When changing focus, we don't scroll or change the cursor location
495 PageManager::SetKeyBoardFocus(0);
496 PageManager::NotifyKeyboard(0);
497 SetInputFocus(1);
498 DrawCursor = true;
499 mRendered = false;
500 }
501 } else {
502 switch (state) {
503 case TOUCH_HOLD:
504 case TOUCH_REPEAT:
505 break;
506 case TOUCH_START:
507 startSelection = GetSelection(x,y);
508 lastX = x;
509 DrawCursor = false;
510 mRendered = false;
511 break;
512
513 case TOUCH_DRAG:
514 // Check if we dragged out of the selection window
515 if (GetSelection(x, y) == -1) {
516 lastX = 0;
517 break;
518 }
519
520 DrawCursor = false;
521
522 // Provide some debounce on initial touches
523 if (startSelection != -1 && abs(x - lastX) < 6) {
524 break;
525 }
526
527 startSelection = -1;
528 if (lastX != x)
529 HandleTextLocation(x);
530 break;
531
532 case TOUCH_RELEASE:
533 // We've moved the cursor location
534 int relativeX = x - mRenderX;
535
536 mRendered = false;
537 DrawCursor = true;
538 DataManager::GetValue(mVariable, displayValue);
539 if (HasMask) {
540 int index, string_size = displayValue.size();
541 string maskedValue;
542 for (index=0; index<string_size; index++)
543 maskedValue += mMask;
544 displayValue = maskedValue;
545 }
546 if (displayValue.size() == 0) {
547 skipChars = 0;
548 mCursorLocation = -1;
549 return 0;
550 } else if (skipChars && skipChars < displayValue.size()) {
551 displayValue.erase(0, skipChars);
552 }
553
554 string cursorString;
555 int cursorX = 0;
556 unsigned index = 0;
557
558 for(index=0; index<displayValue.size(); index++)
559 {
560 cursorString = displayValue.substr(0, index);
561 cursorX = gr_measureEx(cursorString.c_str(), fontResource) + mRenderX;
562 if (cursorX > x) {
563 if (index > 0)
564 mCursorLocation = index - 1;
565 else
566 mCursorLocation = index;
567 return 0;
568 }
569 }
570 mCursorLocation = -1;
571 break;
572 }
573 }
Vojtech Bocekfafb0c52013-07-25 22:53:02 +0200574 return 0;
Dees_Troy51a0e822012-09-05 15:24:24 -0400575}
576
577int GUIInput::NotifyVarChange(std::string varName, std::string value)
578{
579 if (varName == mVariable && !isLocalChange) {
580 HandleTextLocation(-1003);
581 return 0;
582 }
583 return 0;
584}
585
586int GUIInput::NotifyKeyboard(int key)
587{
588 string variableValue;
589
590 if (HasInputFocus) {
591 if (key == KEYBOARD_BACKSPACE) {
592 //Backspace
593 DataManager::GetValue(mVariable, variableValue);
594 if (variableValue.size() > 0 && (mCursorLocation + skipChars != 0 || mCursorLocation == -1)) {
595 if (mCursorLocation == -1) {
596 variableValue.resize(variableValue.size() - 1);
597 } else {
598 variableValue.erase(mCursorLocation + skipChars - 1, 1);
599 if (mCursorLocation > 0)
600 mCursorLocation--;
601 else if (skipChars > 0)
602 skipChars--;
603 }
604 isLocalChange = true;
605 DataManager::SetValue(mVariable, variableValue);
606 isLocalChange = false;
607
608 if (HasMask) {
609 int index, string_size = variableValue.size();
610 string maskedValue;
611 for (index=0; index<string_size; index++)
612 maskedValue += mMask;
613 DataManager::SetValue(mMaskVariable, maskedValue);
614 }
615 HandleTextLocation(-1002);
616 }
617 } else if (key == KEYBOARD_SWIPE_LEFT) {
618 // Delete all
619 isLocalChange = true;
620 if (mCursorLocation == -1) {
621 DataManager::SetValue (mVariable, "");
622 if (HasMask)
623 DataManager::SetValue(mMaskVariable, "");
624 mCursorLocation = -1;
625 } else {
626 DataManager::GetValue(mVariable, variableValue);
627 variableValue.erase(0, mCursorLocation + skipChars);
628 DataManager::SetValue(mVariable, variableValue);
629 if (HasMask) {
630 DataManager::GetValue(mMaskVariable, variableValue);
631 variableValue.erase(0, mCursorLocation + skipChars);
632 DataManager::SetValue(mMaskVariable, variableValue);
633 }
634 mCursorLocation = 0;
635 }
636 skipChars = 0;
637 scrollingX = 0;
638 mInputText->SkipCharCount(skipChars);
639 isLocalChange = false;
640 mRendered = false;
641 return 0;
642 } else if (key == KEYBOARD_ARROW_LEFT) {
643 if (mCursorLocation == 0 && skipChars == 0)
644 return 0; // we're already at the beginning
645 if (mCursorLocation == -1) {
646 DataManager::GetValue(mVariable, variableValue);
647 if (variableValue.size() == 0)
648 return 0;
649 mCursorLocation = variableValue.size() - skipChars - 1;
650 } else if (mCursorLocation == 0) {
651 skipChars--;
652 HandleTextLocation(-1002);
653 } else {
654 mCursorLocation--;
655 HandleTextLocation(-1002);
656 }
657 mRendered = false;
658 return 0;
659 } else if (key == KEYBOARD_ARROW_RIGHT) {
660 if (mCursorLocation == -1)
661 return 0; // we're already at the end
662 mCursorLocation++;
663 DataManager::GetValue(mVariable, variableValue);
664 if (variableValue.size() <= mCursorLocation + skipChars)
665 mCursorLocation = -1;
666 HandleTextLocation(-1001);
667 mRendered = false;
668 return 0;
669 } else if (key == KEYBOARD_HOME || key == KEYBOARD_ARROW_UP) {
670 DataManager::GetValue(mVariable, variableValue);
671 if (variableValue.size() == 0)
672 return 0;
673 mCursorLocation = 0;
674 skipChars = 0;
675 mRendered = false;
676 HandleTextLocation(-1002);
677 return 0;
678 } else if (key == KEYBOARD_END || key == KEYBOARD_ARROW_DOWN) {
679 mCursorLocation = -1;
680 mRendered = false;
681 HandleTextLocation(-1003);
682 return 0;
683 } else if (key < KEYBOARD_SPECIAL_KEYS && key > 0) {
684 // Regular key
685 if (HasAllowed && AllowedList.find((char)key) == string::npos) {
686 return 0;
687 }
688 if (HasDisabled && DisabledList.find((char)key) != string::npos) {
689 return 0;
690 }
691 DataManager::GetValue(mVariable, variableValue);
692 if (MaxLen != 0 && variableValue.size() >= MaxLen) {
693 return 0;
694 }
695 if (mCursorLocation == -1) {
696 variableValue += key;
697 } else {
698 const char newchar = (char)key;
699 const char* a = &newchar;
700 string newstring = a;
701 newstring.resize(1);
702 variableValue.insert(mCursorLocation + skipChars, newstring);
703 mCursorLocation++;
704 }
705 isLocalChange = true;
706 DataManager::SetValue(mVariable, variableValue);
707 HandleTextLocation(-1001);
708 isLocalChange = false;
709
710 if (HasMask) {
711 int index, string_size = variableValue.size();
712 string maskedValue;
713 for (index=0; index<string_size; index++)
714 maskedValue += mMask;
715 DataManager::SetValue(mMaskVariable, maskedValue);
716 }
717 } else if (key == KEYBOARD_ACTION) {
718 // Action
719 DataManager::GetValue(mVariable, variableValue);
720 if (mAction) {
721 unsigned inputLen = variableValue.length();
722 if (inputLen < MinLen)
723 return 0;
724 else if (MaxLen != 0 && inputLen > MaxLen)
725 return 0;
726 else
727 return (mAction ? mAction->NotifyTouch(TOUCH_RELEASE, mRenderX, mRenderY) : 1);
728 }
729 }
730 return 0;
731 } else {
732 if (key == 0) {
733 // Somewhat ugly hack-ish way to tell the box to redraw after losing focus to remove the cursor
734 mRendered = false;
735 return 1;
736 }
737 }
738 return 1;
739}