gui: simplify code in GUIKeyboard

- merge duplicated code into new ParseKey method
- convert some unsigned int to int to avoid warnings
- add local variable for current key in NotifyTouch to reduce clutter

Change-Id: I98ddbaca50d487c97ab6e98938df91ef03b9aed5
diff --git a/gui/keyboard.cpp b/gui/keyboard.cpp
index bb52d55..bbc6ed2 100644
--- a/gui/keyboard.cpp
+++ b/gui/keyboard.cpp
@@ -60,7 +60,7 @@
 	mRendered = false;
 	currentLayout = 1;
 	mAction = NULL;
-	KeyboardHeight = KeyboardWidth = cursorLocation = 0;
+	KeyboardHeight = KeyboardWidth = 0;
 
 	if (!node)  return;
 
@@ -171,136 +171,35 @@
 			attr = keyrow->first_attribute(key);
 
 			while (attr) {
-				string stratt;
-				char keyinfo[255];
-
 				if (keyindex > MAX_KEYBOARD_KEYS) {
 					LOGERR("Too many keys defined in a keyboard row.\n");
 					return;
 				}
 
-				stratt = attr->value();
-				if (strlen(stratt.c_str()) >= 255) {
-					LOGERR("Key info on layout%i, row%i, key%dd is too long.\n", layoutindex, rowindex, keyindex);
-					return;
-				}
-
-				strcpy(keyinfo, stratt.c_str());
+				const char* keyinfo = attr->value();
 
 				if (strlen(keyinfo) == 0) {
 					LOGERR("No key info on layout%i, row%i, key%dd.\n", layoutindex, rowindex, keyindex);
 					return;
 				}
 
-				if (strlen(keyinfo) == 1) {
-					// This is a single key, simple definition
-					keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].key = keyinfo[0];
-					Xindex += keyWidth;
-					keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].end_x = Xindex - 1;
-				} else {
-					// This key has extra data
-					char* ptr;
-					char* offset;
-					char* keyitem;
-					char foratoi[10];
+				if (ParseKey(keyinfo, keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1], Xindex, keyWidth, false))
+					LOGERR("Invalid key info on layout%i, row%i, key%02i.\n", layoutindex, rowindex, keyindex);
 
-					ptr = keyinfo;
-					offset = keyinfo;
-					while (*ptr > 32 && *ptr != ':')
-						ptr++;
-					if (*ptr != 0)
-						*ptr = 0;
-
-					strcpy(foratoi, offset);
-					Xindex += atoi(foratoi);
-					keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].end_x = Xindex - 1;
-
-					ptr++;
-					if (*ptr == 0) {
-						// This is an empty area
-						keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].key = 0;
-					} else if (strlen(ptr) == 1) {
-						// This is the character that this key uses
-						keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].key = *ptr;
-					} else if (*ptr == 'c') {
-						// This is an ASCII character code
-						keyitem = ptr + 2;
-						strcpy(foratoi, keyitem);
-						keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].key = atoi(foratoi);
-					} else if (*ptr == 'l') {
-						// This is a different layout
-						keyitem = ptr + 6;
-						keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].key = KEYBOARD_LAYOUT;
-						strcpy(foratoi, keyitem);
-						keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].layout = atoi(foratoi);
-					} else if (*ptr == 'a') {
-						// This is an action
-						keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].key = KEYBOARD_ACTION;
-					} else
-						LOGERR("Invalid key info on layout%i, row%i, key%02i.\n", layoutindex, rowindex, keyindex);
-				}
 
 				// PROCESS LONG PRESS INFO IF EXISTS
 				sprintf(longpress, "long%02i", keyindex);
 				attr = keyrow->first_attribute(longpress);
 				if (attr) {
-					stratt = attr->value();
-					if (strlen(stratt.c_str()) >= 255) {
-						LOGERR("Key info on layout%i, row%i, key%dd is too long.\n", layoutindex, rowindex, keyindex);
-						return;
-					}
-
-					strcpy(keyinfo, stratt.c_str());
+					const char* keyinfo = attr->value();
 
 					if (strlen(keyinfo) == 0) {
 						LOGERR("No long press info on layout%i, row%i, long%dd.\n", layoutindex, rowindex, keyindex);
 						return;
 					}
 
-					if (strlen(keyinfo) == 1) {
-						// This is a single key, simple definition
-						keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].longpresskey = keyinfo[0];
-					} else {
-						// This key has extra data
-						char* ptr;
-						char* offset;
-						char* keyitem;
-						char foratoi[10];
-
-						ptr = keyinfo;
-						offset = keyinfo;
-						while (*ptr > 32 && *ptr != ':')
-							ptr++;
-						if (*ptr != 0)
-							*ptr = 0;
-
-						strcpy(foratoi, offset);
-						Xindex += atoi(foratoi);
-
-						ptr++;
-						if (*ptr == 0) {
-							// This is an empty area
-							keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].longpresskey = 0;
-						} else if (strlen(ptr) == 1) {
-							// This is the character that this key uses
-							keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].longpresskey = *ptr;
-						} else if (*ptr == 'c') {
-							// This is an ASCII character code
-							keyitem = ptr + 2;
-							strcpy(foratoi, keyitem);
-							keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].longpresskey = atoi(foratoi);
-						} else if (*ptr == 'l') {
-							// This is a different layout
-							keyitem = ptr + 6;
-							keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].longpresskey = KEYBOARD_LAYOUT;
-							strcpy(foratoi, keyitem);
-							keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].layout = atoi(foratoi);
-						} else if (*ptr == 'a') {
-							// This is an action
-							keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1].longpresskey = KEYBOARD_ACTION;
-						} else
-							LOGERR("Invalid long press key info on layout%i, row%i, long%02i.\n", layoutindex, rowindex, keyindex);
-					}
+					if (ParseKey(keyinfo, keyboard_keys[layoutindex - 1][rowindex - 1][keyindex - 1], Xindex, keyWidth, true))
+						LOGERR("Invalid long press key info on layout%i, row%i, long%02i.\n", layoutindex, rowindex, keyindex);
 				}
 				keyindex++;
 				sprintf(key, "key%02i", keyindex);
@@ -325,7 +224,49 @@
 
 GUIKeyboard::~GUIKeyboard()
 {
+}
 
+int GUIKeyboard::ParseKey(const char* keyinfo, keyboard_key_class& key, int& Xindex, int keyWidth, bool longpress)
+{
+	int keychar = 0;
+	if (strlen(keyinfo) == 1) {
+		// This is a single key, simple definition
+		keychar = keyinfo[0];
+	} else {
+		// This key has extra data: {keywidth}:{what_the_key_does}
+		keyWidth = atoi(keyinfo);
+
+		const char* ptr = keyinfo;
+		while (*ptr > 32 && *ptr != ':')
+			ptr++;
+		if (*ptr != ':')
+			return -1;  // no colon is an error
+		ptr++;
+
+		if (*ptr == 0) {  // This is an empty area
+			keychar = 0;
+		} else if (strlen(ptr) == 1) {  // This is the character that this key uses
+			keychar = *ptr;
+		} else if (*ptr == 'c') {  // This is an ASCII character code: "c:{number}"
+			keychar = atoi(ptr + 2);
+		} else if (*ptr == 'l') {  // This is a different layout: "layout{number}"
+			keychar = KEYBOARD_LAYOUT;
+			key.layout = atoi(ptr + 6);
+		} else if (*ptr == 'a') {  // This is an action: "action"
+			keychar = KEYBOARD_ACTION;
+		} else
+			return -1;
+	}
+
+	if (longpress) {
+		key.longpresskey = keychar;
+	} else {
+		key.key = keychar;
+		Xindex += keyWidth;
+		key.end_x = Xindex - 1;
+	}
+
+	return 0;
 }
 
 int GUIKeyboard::Render(void)
@@ -421,7 +362,7 @@
 {
 	static int startSelection = -1, was_held = 0, startX = 0;
 	static unsigned char initial_key = 0;
-	unsigned int indexy, indexx, rely, relx, rowIndex = 0;
+	int indexy, indexx, rely, relx, rowIndex = 0;
 
 	rely = y - mRenderY;
 	relx = x - mRenderX;
@@ -511,36 +452,37 @@
 
 		// Find the correct key (column)
 		for (indexx=0; indexx<MAX_KEYBOARD_KEYS; indexx++) {
-			if (keyboard_keys[currentLayout - 1][rowIndex][indexx].end_x > relx) {
+			keyboard_key_class& key = keyboard_keys[currentLayout - 1][rowIndex][indexx];
+			if (key.end_x > relx) {
 				// This is the key that was pressed!
-				if (keyboard_keys[currentLayout - 1][rowIndex][indexx].key != initial_key) {
+				if (key.key != initial_key) {
 					// We dragged off of the starting key
 					startSelection = 0;
 					break;
 				} else if (state == TOUCH_RELEASE && was_held == 0) {
 					DataManager::Vibrate("tw_keyboard_vibrate");
-					if ((int)keyboard_keys[currentLayout - 1][rowIndex][indexx].key < KEYBOARD_SPECIAL_KEYS && (int)keyboard_keys[currentLayout - 1][rowIndex][indexx].key > 0) {
+					if ((int)key.key < KEYBOARD_SPECIAL_KEYS && (int)key.key > 0) {
 						// Regular key
-						PageManager::NotifyKeyboard(keyboard_keys[currentLayout - 1][rowIndex][indexx].key);
+						PageManager::NotifyKeyboard(key.key);
 						if (caps_tracking[currentLayout - 1].capslock == 0 && !caps_tracking[currentLayout - 1].set_capslock) {
 							// caps lock was not set, change layouts
 							currentLayout = caps_tracking[currentLayout - 1].revert_layout;
 							mRendered = false;
 						}
-					} else if ((int)keyboard_keys[currentLayout - 1][rowIndex][indexx].key == KEYBOARD_LAYOUT) {
+					} else if ((int)key.key == KEYBOARD_LAYOUT) {
 						// Switch layouts
-						if (caps_tracking[currentLayout - 1].capslock == 0 && keyboard_keys[currentLayout - 1][rowIndex][indexx].layout == caps_tracking[currentLayout - 1].revert_layout) {
+						if (caps_tracking[currentLayout - 1].capslock == 0 && key.layout == caps_tracking[currentLayout - 1].revert_layout) {
 							if (!caps_tracking[currentLayout - 1].set_capslock) {
 								caps_tracking[currentLayout - 1].set_capslock = 1; // Set the caps lock
 							} else {
 								caps_tracking[currentLayout - 1].set_capslock = 0; // Unset the caps lock and change layouts
-								currentLayout = keyboard_keys[currentLayout - 1][rowIndex][indexx].layout;
+								currentLayout = key.layout;
 							}
 						} else {
-							currentLayout = keyboard_keys[currentLayout - 1][rowIndex][indexx].layout;
+							currentLayout = key.layout;
 						}
 						mRendered = false;
-					} else if ((int)keyboard_keys[currentLayout - 1][rowIndex][indexx].key == KEYBOARD_ACTION) {
+					} else if ((int)key.key == KEYBOARD_ACTION) {
 						// Action
 						highlightRenderCount = 0;
 						if (mAction) {
@@ -548,24 +490,24 @@
 							return (mAction ? mAction->NotifyTouch(state, x, y) : 1);
 						} else {
 							// Send action notification
-							PageManager::NotifyKeyboard(keyboard_keys[currentLayout - 1][rowIndex][indexx].key);
+							PageManager::NotifyKeyboard(key.key);
 						}
 					}
 				} else if (state == TOUCH_HOLD) {
 					was_held = 1;
-					if ((int)keyboard_keys[currentLayout - 1][rowIndex][indexx].key == KEYBOARD_BACKSPACE) {
+					if ((int)key.key == KEYBOARD_BACKSPACE) {
 						// Repeat backspace
-						PageManager::NotifyKeyboard(keyboard_keys[currentLayout - 1][rowIndex][indexx].key);
-					} else if ((int)keyboard_keys[currentLayout - 1][rowIndex][indexx].longpresskey < KEYBOARD_SPECIAL_KEYS && (int)keyboard_keys[currentLayout - 1][rowIndex][indexx].longpresskey > 0) {
+						PageManager::NotifyKeyboard(key.key);
+					} else if ((int)key.longpresskey < KEYBOARD_SPECIAL_KEYS && (int)key.longpresskey > 0) {
 						// Long Press Key
 						DataManager::Vibrate("tw_keyboard_vibrate");
-						PageManager::NotifyKeyboard(keyboard_keys[currentLayout - 1][rowIndex][indexx].longpresskey);
+						PageManager::NotifyKeyboard(key.longpresskey);
 					}
 				} else if (state == TOUCH_REPEAT) {
 					was_held = 1;
-					if ((int)keyboard_keys[currentLayout - 1][rowIndex][indexx].key == KEYBOARD_BACKSPACE) {
+					if ((int)key.key == KEYBOARD_BACKSPACE) {
 						// Repeat backspace
-						PageManager::NotifyKeyboard(keyboard_keys[currentLayout - 1][rowIndex][indexx].key);
+						PageManager::NotifyKeyboard(key.key);
 					}
 				}
 				indexx = MAX_KEYBOARD_KEYS;
diff --git a/gui/objects.hpp b/gui/objects.hpp
index 1d20c2a..3e33561 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -899,9 +899,10 @@
 	{
 		unsigned char key;
 		unsigned char longpresskey;
-		unsigned int end_x;
-		unsigned int layout;
+		int end_x;
+		int layout;
 	};
+	int ParseKey(const char* keyinfo, keyboard_key_class& key, int& Xindex, int keyWidth, bool longpress);
 	struct capslock_tracking_struct
 	{
 		int capslock;
@@ -914,9 +915,8 @@
 	struct capslock_tracking_struct caps_tracking[MAX_KEYBOARD_LAYOUTS];
 	bool mRendered;
 	std::string mVariable;
-	unsigned int cursorLocation;
-	unsigned int currentLayout;
-	unsigned int row_heights[MAX_KEYBOARD_LAYOUTS][MAX_KEYBOARD_ROWS];
+	int currentLayout;
+	int row_heights[MAX_KEYBOARD_LAYOUTS][MAX_KEYBOARD_ROWS];
 	unsigned int KeyboardWidth, KeyboardHeight;
 	int rowY, colX, highlightRenderCount, hasHighlight, hasCapsHighlight;
 	GUIAction* mAction;