// text.cpp - GUIText object
#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"
GUIText::GUIText(xml_node<>* node)
: Conditional(node)
{
xml_attribute<>* attr;
xml_node<>* child;
mFont = NULL;
mIsStatic = 1;
mVarChanged = 0;
mFontHeight = 0;
maxWidth = 0;
charSkip = 0;
isHighlighted = false;
hasHighlightColor = false;
if (!node) return;
// Initialize color to solid black
memset(&mColor, 0, sizeof(COLOR));
mColor.alpha = 255;
memset(&mHighlightColor, 0, sizeof(COLOR));
mHighlightColor.alpha = 255;
attr = node->first_attribute("color");
if (attr)
{
std::string color = attr->value();
ConvertStrToColor(color, &mColor);
}
attr = node->first_attribute("highlightcolor");
if (attr)
{
std::string color = attr->value();
ConvertStrToColor(color, &mHighlightColor);
hasHighlightColor = true;
}
// 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());
attr = child->first_attribute("color");
if (attr)
{
std::string color = attr->value();
ConvertStrToColor(color, &mColor);
}
attr = child->first_attribute("highlightcolor");
if (attr)
{
std::string color = attr->value();
ConvertStrToColor(color, &mHighlightColor);
hasHighlightColor = true;
}
}
// Load the placement
LoadPlacement(node->first_node("placement"), &mRenderX, &mRenderY, &mRenderW, &mRenderH, &mPlacement);
child = node->first_node("text");
if (child) mText = child->value();
// Simple way to check for static state
mLastValue = parseText();
if (mLastValue != mText) mIsStatic = 0;
gr_getFontDetails(mFont ? mFont->GetResource() : NULL, (unsigned*) &mFontHeight, NULL);
return;
}
int GUIText::Render(void)
{
if (!isConditionTrue()) return 0;
void* fontResource = NULL;
string displayValue;
if (mFont) fontResource = mFont->GetResource();
mLastValue = parseText();
displayValue = mLastValue;
if (charSkip)
displayValue.erase(0, charSkip);
mVarChanged = 0;
int x = mRenderX, y = mRenderY;
int width = gr_measureEx(displayValue.c_str(), fontResource);
if (mPlacement != TOP_LEFT && mPlacement != BOTTOM_LEFT)
{
if (mPlacement == CENTER || mPlacement == CENTER_X_ONLY)
x -= (width / 2);
else
x -= width;
}
if (mPlacement != TOP_LEFT && mPlacement != TOP_RIGHT)
{
if (mPlacement == CENTER)
y -= (mFontHeight / 2);
else if (mPlacement == BOTTOM_LEFT || mPlacement == BOTTOM_RIGHT)
y -= mFontHeight;
}
if (hasHighlightColor && isHighlighted)
gr_color(mHighlightColor.red, mHighlightColor.green, mHighlightColor.blue, mHighlightColor.alpha);
else
gr_color(mColor.red, mColor.green, mColor.blue, mColor.alpha);
if (maxWidth)
gr_textExW(x, y, displayValue.c_str(), fontResource, maxWidth + x);
else
gr_textEx(x, y, displayValue.c_str(), fontResource);
return 0;
}
int GUIText::Update(void)
{
if (!isConditionTrue()) return 0;
static int updateCounter = 3;
// This hack just makes sure we update at least once a minute for things like clock and battery
if (updateCounter) updateCounter--;
else
{
mVarChanged = 1;
updateCounter = 3;
}
if (mIsStatic || !mVarChanged) return 0;
std::string newValue = parseText();
if (mLastValue == newValue)
return 0;
else
mLastValue = newValue;
return 2;
}
int GUIText::GetCurrentBounds(int& w, int& h)
{
void* fontResource = NULL;
if (mFont) fontResource = mFont->GetResource();
h = mFontHeight;
mLastValue = parseText();
w = gr_measureEx(mLastValue.c_str(), fontResource);
return 0;
}
std::string GUIText::parseText(void)
{
static int counter = 0;
std::string str = mText;
size_t pos = 0;
size_t next = 0, end = 0;
while (1)
{
next = str.find('%', pos);
if (next == std::string::npos) return str;
end = str.find('%', next + 1);
if (end == std::string::npos) return str;
// We have a block of data
std::string var = str.substr(next + 1, (end - next) - 1);
str.erase(next, (end - next) + 1);
if (next + 1 == end)
{
str.insert(next, 1, '%');
}
else
{
std::string value;
if (DataManager::GetValue(var, value) == 0)
str.insert(next, value);
}
pos = next + 1;
}
}
int GUIText::NotifyVarChange(std::string varName, std::string value)
{
mVarChanged = 1;
return 0;
}
int GUIText::SetMaxWidth(unsigned width)
{
maxWidth = width;
mVarChanged = 1;
return 0;
}
int GUIText::SkipCharCount(unsigned skip)
{
charSkip = skip;
mVarChanged = 1;
return 0;
}