Add word wrap to console output and fix scrolling in console

Change-Id: Ibcf89952ee1391350c715f1ec82cf0cdb9b0ca7d
diff --git a/gui/console.cpp b/gui/console.cpp
index 5d0ed3e..51ad21e 100644
--- a/gui/console.cpp
+++ b/gui/console.cpp
@@ -117,7 +117,9 @@
 	mScrollColor.alpha = 255;
 	mLastCount = 0;
 	mSlideout = 0;
+	RenderCount = 0;
 	mSlideoutState = hidden;
+	mRender = true;
 
 	mRenderX = 0; mRenderY = 0; mRenderW = gr_fb_width(); mRenderH = gr_fb_height();
 
@@ -211,21 +213,42 @@
 	gr_color(mForegroundColor.red, mForegroundColor.green, mForegroundColor.blue, mForegroundColor.alpha);
 
 	// Don't try to continue to render without data
+	int prevCount = mLastCount;
 	mLastCount = gConsole.size();
+	mRender = false;
 	if (mLastCount == 0)
 		return (mSlideout ? RenderSlideout() : 0);
 
+	// Due to word wrap, figure out what / how the newly added text needs to be added to the render vector that is word wrapped
+	// Note, that multiple consoles on different GUI pages may be different widths or use different fonts, so the word wrapping
+	// may different in different console windows
+	for (int i = prevCount; i < mLastCount; i++) {
+		string curr_line = gConsole[i];
+		int line_char_width;
+		for(;;) {
+			line_char_width = gr_maxExW(curr_line.c_str(), fontResource, mConsoleW);
+			if (line_char_width < curr_line.size()) {
+				rConsole.push_back(curr_line.substr(0, line_char_width));
+				curr_line = curr_line.substr(line_char_width, curr_line.size() - line_char_width - 1);
+			} else {
+				rConsole.push_back(curr_line);
+				break;
+			}
+		}
+	}
+	RenderCount = rConsole.size();
+
 	// Find the start point
 	int start;
 	int curLine = mCurrentLine; // Thread-safing (Another thread updates this value)
 	if (curLine == -1)
 	{
-		start = mLastCount - mMaxRows;
+		start = RenderCount - mMaxRows;
 	}
 	else
 	{
-		if (curLine > (int) mLastCount)
-			curLine = (int) mLastCount;
+		if (curLine > (int) RenderCount)
+			curLine = (int) RenderCount;
 		if ((int) mMaxRows > curLine)
 			curLine = (int) mMaxRows;
 		start = curLine - mMaxRows;
@@ -234,8 +257,8 @@
 	unsigned int line;
 	for (line = 0; line < mMaxRows; line++)
 	{
-		if ((start + (int) line) >= 0 && (start + (int) line) < (int) mLastCount)
-			gr_textExW(mConsoleX, mStartY + (line * mFontHeight), gConsole[start + line].c_str(), fontResource, mConsoleW + mConsoleX);
+		if ((start + (int) line) >= 0 && (start + (int) line) < (int) RenderCount)
+			gr_textExW(mConsoleX, mStartY + (line * mFontHeight), rConsole[start + line].c_str(), fontResource, mConsoleW + mConsoleX);
 	}
 	return (mSlideout ? RenderSlideout() : 0);
 }
@@ -278,11 +301,10 @@
 		Render();
 		return 2;
 	}
-	else if (mLastTouchY >= 0)
+	else if (mRender)
 	{
 		// They're still touching, so re-render
 		Render();
-		mLastTouchY = -1;
 		return 2;
 	}
 	return 0;
@@ -354,7 +376,7 @@
 	}
 
 	// If we don't have enough lines to scroll, throw this away.
-	if (mLastCount < mMaxRows)   return 1;
+	if (RenderCount < mMaxRows)   return 1;
 
 	// We are scrolling!!!
 	switch (state)
@@ -362,47 +384,33 @@
 	case TOUCH_START:
 		mLastTouchX = x;
 		mLastTouchY = y;
-		if ((x - mConsoleX) > ((9 * mConsoleW) / 10))
-			mSlideMultiplier = 10;
-		else
-			mSlideMultiplier = 1;
 		break;
 
 	case TOUCH_DRAG:
-		// This handles tapping
-		if (x == mLastTouchX && y == mLastTouchY)   break;
-		mLastTouchX = -1;
-
-		if (y > mLastTouchY + 5)
-		{
-			mLastTouchY = y;
-			if (mCurrentLine == -1)
-				mCurrentLine = mLastCount - 1;
-			else if (mCurrentLine > mSlideMultiplier)
-				mCurrentLine -= mSlideMultiplier;
-			else
-				mCurrentLine = mMaxRows;
-
-			if (mCurrentLine < (int) mMaxRows)
-				mCurrentLine = mMaxRows;
-		}
-		else if (y < mLastTouchY - 5)
-		{
-			mLastTouchY = y;
-			if (mCurrentLine >= 0)
-			{
-				mCurrentLine += mSlideMultiplier;
-				if (mCurrentLine >= (int) mLastCount)
-					mCurrentLine = -1;
+		if (x < mConsoleX || x > mConsoleX + mConsoleW || y < mConsoleY || y > mConsoleY + mConsoleH)
+			break; // touch is outside of the console area -- do nothing
+		if (y > mLastTouchY + mFontHeight) {
+			while (y > mLastTouchY + mFontHeight) {
+				if (mCurrentLine == -1)
+					mCurrentLine = RenderCount - 1;
+				else if (mCurrentLine > mMaxRows)
+					mCurrentLine--;
+				mLastTouchY += mFontHeight;
 			}
+			mRender = true;
+		} else if (y < mLastTouchY - mFontHeight) {
+			while (y < mLastTouchY - mFontHeight) {
+				if (mCurrentLine >= 0)
+					mCurrentLine++;
+				mLastTouchY -= mFontHeight;
+			}
+			if (mCurrentLine >= (int) RenderCount)
+				mCurrentLine = -1;
+			mRender = true;
 		}
 		break;
 
 	case TOUCH_RELEASE:
-		// On a tap, we jump to the tail
-		if (mLastTouchX >= 0)
-			mCurrentLine = -1;
-
 		mLastTouchY = -1;
 	case TOUCH_REPEAT:
 	case TOUCH_HOLD:
diff --git a/gui/objects.hpp b/gui/objects.hpp
index f8a4e8c..4942cd7 100644
--- a/gui/objects.hpp
+++ b/gui/objects.hpp
@@ -339,15 +339,17 @@
 	unsigned int mFontHeight;
 	int mCurrentLine;
 	unsigned int mLastCount;
+	unsigned int RenderCount;
 	unsigned int mMaxRows;
 	int mStartY;
 	int mSlideoutX, mSlideoutY, mSlideoutW, mSlideoutH;
 	int mSlideinX, mSlideinY, mSlideinW, mSlideinH;
 	int mConsoleX, mConsoleY, mConsoleW, mConsoleH;
 	int mLastTouchX, mLastTouchY;
-	int mSlideMultiplier;
 	int mSlideout;
 	SlideoutState mSlideoutState;
+	std::vector<std::string> rConsole;
+	bool mRender;
 
 protected:
 	virtual int RenderSlideout(void);
diff --git a/minuitwrp/graphics.c b/minuitwrp/graphics.c
index ddff571..3a35c58 100644
--- a/minuitwrp/graphics.c
+++ b/minuitwrp/graphics.c
@@ -311,6 +311,30 @@
     return total;
 }
 
+int gr_maxExW(const char *s, void* font, int max_width)
+{
+    GRFont* fnt = (GRFont*) font;
+    int total = 0;
+    unsigned pos;
+    unsigned off;
+
+    if (!fnt)   fnt = gr_font;
+
+    while ((off = *s++))
+    {
+        off -= 32;
+        if (off < 96) {
+            max_width -= (fnt->offset[off+1] - fnt->offset[off]);
+			if (max_width > 0) {
+				total++;
+			} else {
+				return total;
+			}
+		}
+    }
+    return total;
+}
+
 unsigned character_width(const char *s, void* pFont)
 {
 	GRFont *font = (GRFont*) pFont;
diff --git a/minuitwrp/minui.h b/minuitwrp/minui.h
index bbdfdfb..cf90532 100644
--- a/minuitwrp/minui.h
+++ b/minuitwrp/minui.h
@@ -39,6 +39,7 @@
 static inline int gr_text(int x, int y, const char *s)     { return gr_textEx(x, y, s, NULL); }
 int gr_measureEx(const char *s, void* font);
 static inline int gr_measure(const char *s)                { return gr_measureEx(s, NULL); }
+int gr_maxExW(const char *s, void* font, int max_width);
 
 int gr_getFontDetails(void* font, unsigned* cheight, unsigned* maxwidth);
 static inline void gr_font_size(int *x, int *y)            { gr_getFontDetails(NULL, (unsigned*) y, (unsigned*) x); }