TWRP-ify AOSP code

Pull in most TWRP sources
Stub out partition management code
Make it compile -- probably will not boot
Kind of a mess but have to start somewhere
diff --git a/gui/input.cpp b/gui/input.cpp
new file mode 100644
index 0000000..2418c4c
--- /dev/null
+++ b/gui/input.cpp
@@ -0,0 +1,738 @@
+// input.cpp - GUIInput object
+
+#include <linux/input.h>
+#include <pthread.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <fcntl.h>
+#include <sys/reboot.h>
+#include <sys/stat.h>
+#include <sys/time.h>
+#include <sys/mman.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdlib.h>
+
+#include <string>
+
+extern "C" {
+#include "../common.h"
+#include "../minuitwrp/minui.h"
+#include "../recovery_ui.h"
+}
+
+#include "rapidxml.hpp"
+#include "objects.hpp"
+#include "../data.hpp"
+
+GUIInput::GUIInput(xml_node<>* node)
+    : Conditional(node)
+{
+    xml_attribute<>* attr;
+    xml_node<>* child;
+
+    mInputText = NULL;
+	mAction = NULL;
+	mBackground = NULL;
+	mCursor = NULL;
+	mFont = NULL;
+    mRendered = false;
+	HasMask = false;
+	DrawCursor = false;
+	isLocalChange = true;
+	HasAllowed = false;
+	HasDisabled = false;
+	skipChars = scrollingX = mFontHeight = mFontY = lastX = 0;
+	mBackgroundX = mBackgroundY = mBackgroundW = mBackgroundH = MinLen = MaxLen = 0;
+	mCursorLocation = -1; // -1 is always the end of the string
+	CursorWidth = 3;
+	ConvertStrToColor("black", &mBackgroundColor);
+	ConvertStrToColor("white", &mCursorColor);
+
+    if (!node)  return;
+
+    // Load text directly from the node
+    mInputText = new GUIText(node);
+	// Load action directly from the node
+	mAction = new GUIAction(node);
+
+	if (mInputText->Render() < 0)
+    {
+        delete mInputText;
+        mInputText = NULL;
+    }
+
+	// Load the background
+	child = node->first_node("background");
+	if (child)
+	{
+		attr = child->first_attribute("resource");
+		if (attr)
+			mBackground = PageManager::FindResource(attr->value());
+		attr = child->first_attribute("color");
+		if (attr)
+		{
+			std::string color = attr->value();
+			ConvertStrToColor(color, &mBackgroundColor);
+		}
+	}
+	if (mBackground && mBackground->GetResource())
+	{
+		mBackgroundW = gr_get_width(mBackground->GetResource());
+		mBackgroundH = gr_get_height(mBackground->GetResource());
+	}
+
+	// Load the cursor color
+	child = node->first_node("cursor");
+	if (child)
+	{
+		attr = child->first_attribute("resource");
+		if (attr)
+			mCursor = PageManager::FindResource(attr->value());
+		attr = child->first_attribute("color");
+		if (attr)
+		{
+			std::string color = attr->value();
+			ConvertStrToColor(color, &mCursorColor);
+		}
+		attr = child->first_attribute("hasfocus");
+		if (attr)
+		{
+			std::string color = attr->value();
+			SetInputFocus(atoi(color.c_str()));
+		}
+		attr = child->first_attribute("width");
+		if (attr)
+		{
+			std::string cwidth = gui_parse_text(attr->value());
+			CursorWidth = atoi(cwidth.c_str());
+		}
+	}
+	DrawCursor = HasInputFocus;
+
+	// Load the font, and possibly override the color
+    child = node->first_node("font");
+    if (child)
+    {
+        attr = child->first_attribute("resource");
+        if (attr) {
+            mFont = PageManager::FindResource(attr->value());
+			gr_getFontDetails(mFont ? mFont->GetResource() : NULL, &mFontHeight, NULL);
+		}
+    }
+
+	child = node->first_node("text");
+    if (child)  mText = child->value();
+	mLastValue = gui_parse_text(mText);
+
+	child = node->first_node("data");
+	if (child)
+	{
+		attr = child->first_attribute("name");
+		if (attr)
+			mVariable = attr->value();
+		attr = child->first_attribute("default");
+		if (attr)
+			DataManager::SetValue(mVariable, attr->value());
+		attr = child->first_attribute("mask");
+		if (attr) {
+			mMask = attr->value();
+			HasMask = true;
+		}
+		attr = child->first_attribute("maskvariable");
+		if (attr)
+			mMaskVariable = attr->value();
+		else
+			mMaskVariable = mVariable;
+	}
+
+	// Load input restrictions
+	child = node->first_node("restrict");
+	if (child)
+	{
+		attr = child->first_attribute("minlen");
+		if (attr) {
+			std::string attrib = attr->value();
+			MinLen = atoi(attrib.c_str());
+		}
+		attr = child->first_attribute("maxlen");
+		if (attr) {
+			std::string attrib = attr->value();
+			MaxLen = atoi(attrib.c_str());
+		}
+		attr = child->first_attribute("allow");
+		if (attr) {
+			HasAllowed = true;
+			AllowedList = attr->value();
+		}
+		attr = child->first_attribute("disable");
+		if (attr) {
+			HasDisabled = true;
+			DisabledList = attr->value();
+		}
+	}
+
+    // Load the placement
+	LoadPlacement(node->first_node("placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH);
+	SetActionPos(mRenderX, mRenderY, mRenderW, mRenderH);
+
+	if (mInputText && mFontHeight && mFontHeight < (unsigned)mRenderH) {
+		mFontY = ((mRenderH - mFontHeight) / 2) + mRenderY;
+		mInputText->SetRenderPos(mRenderX, mFontY);
+	} else
+		mFontY = mRenderY;
+
+	if (mInputText)
+		mInputText->SetMaxWidth(mRenderW);
+
+	isLocalChange = false;
+	HandleTextLocation(-3);
+
+    return;
+}
+
+GUIInput::~GUIInput()
+{
+    if (mInputText)     delete mInputText;
+	if (mBackground)    delete mBackground;
+	if (mCursor)        delete mCursor;
+	if (mFont)          delete mFont;
+	if (mAction)        delete mAction;
+}
+
+int GUIInput::HandleTextLocation(int x)
+{
+	int textWidth;
+	string displayValue, originalValue, insertChar;
+	void* fontResource = NULL;
+
+	if (mFont)  fontResource = mFont->GetResource();
+
+	DataManager::GetValue(mVariable, originalValue);
+	displayValue = originalValue;
+	if (HasMask) {
+		int index, string_size = displayValue.size();
+		string maskedValue;
+		for (index=0; index<string_size; index++)
+			maskedValue += mMask;
+		displayValue = maskedValue;
+	}
+	textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+	if (textWidth <= mRenderW) {
+		lastX = x;
+		scrollingX = 0;
+		skipChars = 0;
+		mInputText->SkipCharCount(skipChars);
+		mRendered = false;
+		return 0;
+	}
+	if (skipChars && skipChars < displayValue.size()) {
+		displayValue.erase(0, skipChars);
+	}
+	textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+	mRendered = false;
+
+	int deltaX, deltaText, newWidth;
+
+	if (x < -1000) {
+		// No change in scrolling
+		if (x == -1003) {
+			mCursorLocation = -1;
+		}
+		if (mCursorLocation == -1) {
+			displayValue = originalValue;
+			skipChars = 0;
+			textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+			while (textWidth > mRenderW) {
+				displayValue.erase(0, 1);
+				skipChars++;
+				textWidth = gr_measureEx(displayValue.c_str(), fontResource);
+			}
+			scrollingX = mRenderW - textWidth;
+			mInputText->SkipCharCount(skipChars);
+		} else if (x == -1001) {
+			// Added a new character
+			int adjust_scrollingX = 0;
+			string cursorLocate;
+
+			cursorLocate = displayValue;
+			cursorLocate.resize(mCursorLocation);
+			textWidth = gr_measureEx(cursorLocate.c_str(), fontResource);
+			while (textWidth > mRenderW) {
+				skipChars++;
+				mCursorLocation--;
+				cursorLocate.erase(0, 1);
+				textWidth = gr_measureEx(cursorLocate.c_str(), fontResource);
+				adjust_scrollingX = -1;
+			}
+			if (adjust_scrollingX) {
+				scrollingX = mRenderW - textWidth;
+				if (scrollingX < 0)
+					scrollingX = 0;
+			}
+			mInputText->SkipCharCount(skipChars);
+		} else if (x == -1002) {
+			// Deleted a character
+			while (-1) {
+				if (skipChars == 0) {
+					scrollingX = 0;
+					mInputText->SkipCharCount(skipChars);
+					return 0;
+				}
+				insertChar = originalValue.substr(skipChars - 1, 1);
+				displayValue.insert(0, insertChar);
+				newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+				deltaText = newWidth - textWidth;
+				if (newWidth > mRenderW) {
+					scrollingX = mRenderW - textWidth;
+					if (scrollingX < 0)
+						scrollingX = 0;
+					mInputText->SkipCharCount(skipChars);
+					return 0;
+				} else {
+					textWidth = newWidth;
+					skipChars--;
+					mCursorLocation++;
+				}
+			}
+		} else
+			LOGI("GUIInput::HandleTextLocation -> We really shouldn't ever get here...\n");
+	} else if (x > lastX) {
+		// Dragging to right, scrolling left
+		while (-1) {
+			deltaX = x - lastX + scrollingX;
+			if (skipChars == 0 || deltaX == 0) {
+				scrollingX = 0;
+				lastX = x;
+				mInputText->SkipCharCount(skipChars);
+				return 0;
+			}
+			insertChar = originalValue.substr(skipChars - 1, 1);
+			displayValue.insert(0, insertChar);
+			newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+			deltaText = newWidth - textWidth;
+			if (deltaText < deltaX) {
+				lastX += deltaText;
+				textWidth = newWidth;
+				skipChars--;
+			} else {
+				scrollingX = deltaX;
+				lastX = x;
+				mInputText->SkipCharCount(skipChars);
+				return 0;
+			}
+		}
+	} else if (x < lastX) {
+		// Dragging to left, scrolling right
+		if (textWidth <= mRenderW) {
+			lastX = x;
+			scrollingX = mRenderW - textWidth;
+			return 0;
+		}
+		if (scrollingX) {
+			deltaX = lastX - x;
+			if (scrollingX > deltaX) {
+				scrollingX -= deltaX;
+				lastX = x;
+				return 0;
+			} else {
+				lastX -= deltaX;
+				scrollingX = 0;
+			}
+		}
+		while (-1) {
+			deltaX = lastX - x;
+			displayValue.erase(0, 1);
+			skipChars++;
+			newWidth = gr_measureEx(displayValue.c_str(), fontResource);
+			deltaText = textWidth - newWidth;
+			if (newWidth <= mRenderW) {
+				scrollingX = mRenderW - newWidth;
+				lastX = x;
+				mInputText->SkipCharCount(skipChars);
+				return 0;
+			}
+			if (deltaText < deltaX) {
+				lastX -= deltaText;
+				textWidth = newWidth;
+			} else {
+				scrollingX = deltaText - deltaX;
+				lastX = x;
+				mInputText->SkipCharCount(skipChars);
+				return 0;
+			}
+		}
+	}
+	return 0;
+}
+
+int GUIInput::Render(void)
+{
+	if (!isConditionTrue())
+    {
+        mRendered = false;
+        return 0;
+    }
+
+	void* fontResource = NULL;
+	if (mFont)  fontResource = mFont->GetResource();
+
+    // First step, fill background
+	gr_color(mBackgroundColor.red, mBackgroundColor.green, mBackgroundColor.blue, 255);
+	gr_fill(mRenderX, mRenderY, mRenderW, mRenderH);
+
+	// Next, render the background resource (if it exists)
+	if (mBackground && mBackground->GetResource())
+	{
+		mBackgroundX = mRenderX + ((mRenderW - mBackgroundW) / 2);
+		mBackgroundY = mRenderY + ((mRenderH - mBackgroundH) / 2);
+		gr_blit(mBackground->GetResource(), 0, 0, mBackgroundW, mBackgroundH, mBackgroundX, mBackgroundY);
+	}
+
+	int ret = 0;
+
+    // Render the text
+	mInputText->SetRenderPos(mRenderX + scrollingX, mFontY);
+	mInputText->SetMaxWidth(mRenderW - scrollingX);
+	if (mInputText)     ret = mInputText->Render();
+    if (ret < 0)        return ret;
+
+	if (HasInputFocus && DrawCursor) {
+		// Render the cursor
+		string displayValue;
+		int cursorX;
+		DataManager::GetValue(mVariable, displayValue);
+		if (HasMask) {
+			int index, string_size = displayValue.size();
+			string maskedValue;
+			for (index=0; index<string_size; index++)
+				maskedValue += mMask;
+			displayValue = maskedValue;
+		}
+		if (displayValue.size() == 0) {
+			skipChars = 0;
+			mCursorLocation = -1;
+			cursorX = mRenderX;
+		} else {
+			if (skipChars && skipChars < displayValue.size()) {
+				displayValue.erase(0, skipChars);
+			}
+			if (mCursorLocation == 0) {
+				// Cursor is at the beginning
+				cursorX = mRenderX;
+			} else if (mCursorLocation > 0) {
+				// Cursor is in the middle
+				if (displayValue.size() > (unsigned)mCursorLocation) {
+					string cursorDisplay;
+
+					cursorDisplay = displayValue;
+					cursorDisplay.resize(mCursorLocation);
+					cursorX = gr_measureEx(cursorDisplay.c_str(), fontResource) + mRenderX;
+				} else {
+					// Cursor location is after the end of the text  - reset to -1
+					mCursorLocation = -1;
+					cursorX = gr_measureEx(displayValue.c_str(), fontResource) + mRenderX;
+				}
+			} else {
+				// Cursor is at the end (-1)
+				cursorX = gr_measureEx(displayValue.c_str(), fontResource) + mRenderX;
+			}
+		}
+		cursorX += scrollingX;
+		// Make sure that the cursor doesn't go past the boundaries of the box
+		if (cursorX + (int)CursorWidth > mRenderX + mRenderW)
+			cursorX = mRenderX + mRenderW - CursorWidth;
+
+		// Set the color for the cursor
+		gr_color(mCursorColor.red, mCursorColor.green, mCursorColor.blue, 255);
+		gr_fill(cursorX, mFontY, CursorWidth, mFontHeight);
+	}
+
+    mRendered = true;
+    return ret;
+}
+
+int GUIInput::Update(void)
+{
+    if (!isConditionTrue())     return (mRendered ? 2 : 0);
+    if (!mRendered)             return 2;
+
+    int ret = 0;
+
+    if (mInputText)         ret = mInputText->Update();
+    if (ret < 0)            return ret;
+
+    return ret;
+}
+
+int GUIInput::GetSelection(int x, int y)
+{
+	if (x < mRenderX || x - mRenderX > mRenderW || y < mRenderY || y - mRenderY > mRenderH) return -1;
+	return (x - mRenderX);
+}
+
+int GUIInput::NotifyTouch(TOUCH_STATE state, int x, int y)
+{
+    static int startSelection = -1;
+	int textWidth;
+	string displayValue, originalValue;
+	void* fontResource = NULL;
+
+	if (mFont)  fontResource = mFont->GetResource();
+
+	if (!isConditionTrue())     return -1;
+
+	if (!HasInputFocus) {
+		if (state != TOUCH_RELEASE)
+			return 0; // Only change focus if touch releases within the input box
+		if (GetSelection(x, y) >= 0) {
+			// When changing focus, we don't scroll or change the cursor location
+			PageManager::SetKeyBoardFocus(0);
+			PageManager::NotifyKeyboard(0);
+			SetInputFocus(1);
+			DrawCursor = true;
+			mRendered = false;
+		}
+	} else {
+		switch (state) {
+		case TOUCH_HOLD:
+		case TOUCH_REPEAT:
+			break;
+		case TOUCH_START:
+			startSelection = GetSelection(x,y);
+			lastX = x;
+			DrawCursor = false;
+			mRendered = false;
+			break;
+
+		case TOUCH_DRAG:
+			// Check if we dragged out of the selection window
+			if (GetSelection(x, y) == -1) {
+				lastX = 0;
+				break;
+			}
+
+			DrawCursor = false;
+
+			// Provide some debounce on initial touches
+			if (startSelection != -1 && abs(x - lastX) < 6) {
+				break;
+			}
+
+			startSelection = -1;
+			if (lastX != x)
+				HandleTextLocation(x);
+			break;
+
+		case TOUCH_RELEASE:
+			// We've moved the cursor location
+			int relativeX = x - mRenderX;
+
+			mRendered = false;
+			DrawCursor = true;
+			DataManager::GetValue(mVariable, displayValue);
+			if (HasMask) {
+				int index, string_size = displayValue.size();
+				string maskedValue;
+				for (index=0; index<string_size; index++)
+					maskedValue += mMask;
+				displayValue = maskedValue;
+			}
+			if (displayValue.size() == 0) {
+				skipChars = 0;
+				mCursorLocation = -1;
+				return 0;
+			} else if (skipChars && skipChars < displayValue.size()) {
+				displayValue.erase(0, skipChars);
+			}
+
+			string cursorString;
+			int cursorX = 0;
+			unsigned index = 0;
+
+			for(index=0; index<displayValue.size(); index++)
+			{
+				cursorString = displayValue.substr(0, index);
+				cursorX = gr_measureEx(cursorString.c_str(), fontResource) + mRenderX;
+				if (cursorX > x) {
+					if (index > 0)
+						mCursorLocation = index - 1;
+					else
+						mCursorLocation = index;
+					return 0;
+				}
+			}
+			mCursorLocation = -1;
+			break;
+		}
+	}
+    return 0;
+}
+
+int GUIInput::NotifyVarChange(std::string varName, std::string value)
+{
+	if (varName == mVariable && !isLocalChange) {
+		HandleTextLocation(-1003);
+		return 0;
+	}
+	return 0;
+}
+
+int GUIInput::NotifyKeyboard(int key)
+{
+	string variableValue;
+
+	if (HasInputFocus) {
+		if (key == KEYBOARD_BACKSPACE) {
+			//Backspace
+			DataManager::GetValue(mVariable, variableValue);
+			if (variableValue.size() > 0 && (mCursorLocation + skipChars != 0 || mCursorLocation == -1)) {
+				if (mCursorLocation == -1) {
+					variableValue.resize(variableValue.size() - 1);
+				} else {
+					variableValue.erase(mCursorLocation + skipChars - 1, 1);
+					if (mCursorLocation > 0)
+						mCursorLocation--;
+					else if (skipChars > 0)
+						skipChars--;
+				}
+				isLocalChange = true;
+				DataManager::SetValue(mVariable, variableValue);
+				isLocalChange = false;
+
+				if (HasMask) {
+					int index, string_size = variableValue.size();
+					string maskedValue;
+					for (index=0; index<string_size; index++)
+						maskedValue += mMask;
+					DataManager::SetValue(mMaskVariable, maskedValue);
+				}
+				HandleTextLocation(-1002);
+			}
+		} else if (key == KEYBOARD_SWIPE_LEFT) {
+			// Delete all
+			isLocalChange = true;
+			if (mCursorLocation == -1) {
+				DataManager::SetValue (mVariable, "");
+				if (HasMask)
+					DataManager::SetValue(mMaskVariable, "");
+				mCursorLocation = -1;
+			} else {
+				DataManager::GetValue(mVariable, variableValue);
+				variableValue.erase(0, mCursorLocation + skipChars);
+				DataManager::SetValue(mVariable, variableValue);
+				if (HasMask) {
+					DataManager::GetValue(mMaskVariable, variableValue);
+					variableValue.erase(0, mCursorLocation + skipChars);
+					DataManager::SetValue(mMaskVariable, variableValue);
+				}
+				mCursorLocation = 0;
+			}
+			skipChars = 0;
+			scrollingX = 0;
+			mInputText->SkipCharCount(skipChars);
+			isLocalChange = false;
+			mRendered = false;
+			return 0;
+		} else if (key == KEYBOARD_ARROW_LEFT) {
+			if (mCursorLocation == 0 && skipChars == 0)
+				return 0; // we're already at the beginning
+			if (mCursorLocation == -1) {
+				DataManager::GetValue(mVariable, variableValue);
+				if (variableValue.size() == 0)
+					return 0;
+				mCursorLocation = variableValue.size() - skipChars - 1;
+			} else if (mCursorLocation == 0) {
+				skipChars--;
+				HandleTextLocation(-1002);
+			} else {
+				mCursorLocation--;
+				HandleTextLocation(-1002);
+			}
+			mRendered = false;
+			return 0;
+		} else if (key == KEYBOARD_ARROW_RIGHT) {
+			if (mCursorLocation == -1)
+				return 0; // we're already at the end
+			mCursorLocation++;
+			DataManager::GetValue(mVariable, variableValue);
+			if (variableValue.size() <= mCursorLocation + skipChars)
+				mCursorLocation = -1;
+			HandleTextLocation(-1001);
+			mRendered = false;
+			return 0;
+		} else if (key == KEYBOARD_HOME || key == KEYBOARD_ARROW_UP) {
+			DataManager::GetValue(mVariable, variableValue);
+			if (variableValue.size() == 0)
+				return 0;
+			mCursorLocation = 0;
+			skipChars = 0;
+			mRendered = false;
+			HandleTextLocation(-1002);
+			return 0;
+		} else if (key == KEYBOARD_END || key == KEYBOARD_ARROW_DOWN) {
+			mCursorLocation = -1;
+			mRendered = false;
+			HandleTextLocation(-1003);
+			return 0;
+		} else if (key < KEYBOARD_SPECIAL_KEYS && key > 0) {
+			// Regular key
+			if (HasAllowed && AllowedList.find((char)key) == string::npos) {
+				return 0;
+			}
+			if (HasDisabled && DisabledList.find((char)key) != string::npos) {
+				return 0;
+			}
+			DataManager::GetValue(mVariable, variableValue);
+			if (MaxLen != 0 && variableValue.size() >= MaxLen) {
+				return 0;
+			}
+			if (mCursorLocation == -1) {
+				variableValue += key;
+			} else {
+				const char newchar = (char)key;
+				const char* a = &newchar;
+				string newstring = a;
+				newstring.resize(1);
+				variableValue.insert(mCursorLocation + skipChars, newstring);
+				mCursorLocation++;
+			}
+			isLocalChange = true;
+			DataManager::SetValue(mVariable, variableValue);
+			HandleTextLocation(-1001);
+			isLocalChange = false;
+
+			if (HasMask) {
+				int index, string_size = variableValue.size();
+				string maskedValue;
+				for (index=0; index<string_size; index++)
+					maskedValue += mMask;
+				DataManager::SetValue(mMaskVariable, maskedValue);
+			}
+		} else if (key == KEYBOARD_ACTION) {
+			// Action
+			DataManager::GetValue(mVariable, variableValue);
+			if (mAction) {
+				unsigned inputLen = variableValue.length();
+				if (inputLen < MinLen)
+					return 0;
+				else if (MaxLen != 0 && inputLen > MaxLen)
+					return 0;
+				else
+					return (mAction ? mAction->NotifyTouch(TOUCH_RELEASE, mRenderX, mRenderY) : 1);
+			}
+		}
+		return 0;
+	} else {
+		if (key == 0) {
+			// Somewhat ugly hack-ish way to tell the box to redraw after losing focus to remove the cursor
+			mRendered = false;
+			return 1;
+		}
+	}
+	return 1;
+}