summaryrefslogtreecommitdiffstats
path: root/screen_ui.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'screen_ui.cpp')
-rw-r--r--screen_ui.cpp553
1 files changed, 435 insertions, 118 deletions
diff --git a/screen_ui.cpp b/screen_ui.cpp
index ff95915..46f4add 100644
--- a/screen_ui.cpp
+++ b/screen_ui.cpp
@@ -30,16 +30,16 @@
#include <vector>
-#include "base/strings.h"
-#include "cutils/properties.h"
+#include <base/strings.h>
+#include <base/stringprintf.h>
+#include <cutils/properties.h>
+
#include "common.h"
#include "device.h"
#include "minui/minui.h"
#include "screen_ui.h"
#include "ui.h"
-
-static int char_width;
-static int char_height;
+#include "cutils/properties.h"
// Return the current time as a double (including fractions of a second).
static double now() {
@@ -58,6 +58,8 @@ ScreenRecoveryUI::ScreenRecoveryUI() :
progressScopeSize(0),
progress(0),
pagesIdentical(false),
+ log_text_cols_(0),
+ log_text_rows_(0),
text_cols_(0),
text_rows_(0),
text_(nullptr),
@@ -66,20 +68,34 @@ ScreenRecoveryUI::ScreenRecoveryUI() :
text_top_(0),
show_text(false),
show_text_ever(false),
+ dialog_icon(NONE),
+ dialog_text(nullptr),
+ dialog_show_log(false),
menu_(nullptr),
+ menu_headers_(nullptr),
+ header_items(0),
show_menu(false),
menu_items(0),
menu_sel(0),
+ sysbar_state(0),
file_viewer_text_(nullptr),
animation_fps(20),
installing_frames(-1),
stage(-1),
- max_stage(-1) {
-
- for (int i = 0; i < 5; i++) {
+ max_stage(-1),
+ rainbow(false),
+ wrap_count(0) {
+
+ headerIcon = nullptr;
+ sysbarBackIcon = nullptr;
+ sysbarBackHighlightIcon = nullptr;
+ sysbarHomeIcon = nullptr;
+ sysbarHomeHighlightIcon = nullptr;
+ for (int i = 0; i < NR_ICONS; i++) {
backgroundIcon[i] = nullptr;
}
pthread_mutex_init(&updateMutex, nullptr);
+ pthread_cond_init(&progressCondition, NULL);
}
// Clear the screen and draw the currently selected background icon (if any).
@@ -101,14 +117,16 @@ void ScreenRecoveryUI::draw_background_locked(Icon icon) {
int textWidth = gr_get_width(text_surface);
int textHeight = gr_get_height(text_surface);
int stageHeight = gr_get_height(stageMarkerEmpty);
+ int availableHeight = icon == INSTALLING_UPDATE && !DialogShowing() && show_text
+ ? 3 * gr_fb_height() / 4 : gr_fb_height();
int sh = (max_stage >= 0) ? stageHeight : 0;
iconX = (gr_fb_width() - iconWidth) / 2;
- iconY = (gr_fb_height() - (iconHeight+textHeight+40+sh)) / 2;
+ iconY = (availableHeight - (iconHeight+textHeight+40+sh)) / 2;
int textX = (gr_fb_width() - textWidth) / 2;
- int textY = ((gr_fb_height() - (iconHeight+textHeight+40+sh)) / 2) + iconHeight + 40;
+ int textY = ((availableHeight - (iconHeight+textHeight+40+sh)) / 2) + iconHeight + 40;
gr_blit(surface, 0, 0, iconWidth, iconHeight, iconX, iconY);
if (stageHeight > 0) {
@@ -122,6 +140,8 @@ void ScreenRecoveryUI::draw_background_locked(Icon icon) {
}
}
+ LOGV("textX=%d textY=%d iconX=%d iconY=%d", textX, textY, iconX, iconY);
+
gr_color(255, 255, 255, 255);
gr_texticon(textX, textY, text_surface);
}
@@ -130,7 +150,7 @@ void ScreenRecoveryUI::draw_background_locked(Icon icon) {
// Draw the progress bar (if any) on the screen. Does not flip pages.
// Should only be called with updateMutex locked.
void ScreenRecoveryUI::draw_progress_locked() {
- if (currentIcon == ERROR) return;
+ if (currentIcon == D_ERROR) return;
if (currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) {
GRSurface* icon = installation[installingFrame];
@@ -142,8 +162,11 @@ void ScreenRecoveryUI::draw_progress_locked() {
int width = gr_get_width(progressBarEmpty);
int height = gr_get_height(progressBarEmpty);
- int dx = (gr_fb_width() - width)/2;
- int dy = (3*gr_fb_height() + iconHeight - 2*height)/4;
+ int bottomOfUsableHeight = show_text ? 3 * gr_fb_height() / 4 : gr_fb_height();
+ int bottomOfIcon = bottomOfUsableHeight / 2 + iconHeight / 2;
+
+ int dx = (gr_fb_width() - width) / 2;
+ int dy = bottomOfIcon + (bottomOfUsableHeight - bottomOfIcon) / 2 - height / 2;
// Erase behind the progress bar (in case this was a progress-only update)
gr_color(0, 0, 0, 255);
@@ -184,13 +207,13 @@ void ScreenRecoveryUI::SetColor(UIElement e) {
break;
case MENU:
case MENU_SEL_BG:
- gr_color(0, 106, 157, 255);
+ gr_color(106, 103, 102, 255);
break;
case MENU_SEL_BG_ACTIVE:
- gr_color(0, 156, 100, 255);
+ gr_color(138, 135, 134, 255);
break;
case MENU_SEL_FG:
- gr_color(255, 255, 255, 255);
+ gr_color(0, 177, 229, 255);
break;
case LOG:
gr_color(196, 196, 196, 255);
@@ -198,6 +221,9 @@ void ScreenRecoveryUI::SetColor(UIElement e) {
case TEXT_FILL:
gr_color(0, 0, 0, 160);
break;
+ case ERROR_TEXT:
+ gr_color(255, 0, 0, 255);
+ break;
default:
gr_color(255, 255, 255, 255);
break;
@@ -213,7 +239,7 @@ void ScreenRecoveryUI::DrawHorizontalRule(int* y) {
void ScreenRecoveryUI::DrawTextLine(int* y, const char* line, bool bold) {
gr_text(4, *y, line, bold);
- *y += char_height + 4;
+ *y += char_height_ + 4;
}
void ScreenRecoveryUI::DrawTextLines(int* y, const char* const* lines) {
@@ -233,63 +259,193 @@ static const char* LONG_PRESS_HELP[] = {
NULL
};
+int ScreenRecoveryUI::draw_header_icon()
+{
+ GRSurface* surface = headerIcon;
+ int iw = header_width_;
+ int ih = header_height_;
+ int ix = (gr_fb_width() - iw) / 2;
+ int iy = 0;
+ gr_blit(surface, 0, 0, iw, ih, ix, iy);
+ return ih;
+}
+
+void ScreenRecoveryUI::draw_menu_item(int textrow, const char *text, int selected)
+{
+ if (selected) {
+ SetColor(MENU_SEL_BG);
+ gr_fill(0, (textrow) * char_height_,
+ gr_fb_width(), (textrow+3) * char_height_ - 1);
+ SetColor(MENU_SEL_FG);
+ gr_text(4, (textrow+1) * char_height_ - 1, text, 0);
+ SetColor(MENU);
+ }
+ else {
+ SetColor(MENU);
+ gr_text(4, (textrow+1) * char_height_ - 1, text, 0);
+ }
+}
+
+void ScreenRecoveryUI::draw_sysbar()
+{
+ GRSurface* surface;
+ int sw = gr_fb_width();
+ int sh = gr_fb_height();
+ int iw;
+ int ih;
+ SetColor(TEXT_FILL);
+ gr_fill(0, sh - sysbar_height_, sw, sh);
+
+ // Left third is back button
+ if (!HasBackKey()) {
+ if (sysbar_state & SYSBAR_BACK) {
+ surface = sysbarBackHighlightIcon;
+ }
+ else {
+ surface = sysbarBackIcon;
+ }
+ iw = gr_get_width(surface);
+ ih = gr_get_height(surface);
+ gr_blit(surface, 0, 0, iw, ih,
+ 1 * (sw / 6) - (iw / 2), sh - ih);
+ }
+
+ // Middle third is home button
+ if (!HasHomeKey()) {
+ if (sysbar_state & SYSBAR_HOME) {
+ surface = sysbarHomeHighlightIcon;
+ }
+ else {
+ surface = sysbarHomeIcon;
+ }
+ iw = gr_get_width(surface);
+ ih = gr_get_height(surface);
+ gr_blit(surface, 0, 0, iw, ih,
+ 3 * (sw / 6) - (iw / 2), sh - ih);
+ }
+}
+
+void ScreenRecoveryUI::draw_dialog()
+{
+ int x, y, w, h;
+
+ if (dialog_icon == HEADLESS) {
+ return;
+ }
+ draw_header_icon();
+ draw_sysbar();
+
+ int iconHeight = gr_get_height(backgroundIcon[dialog_icon]);
+
+ x = (gr_fb_width()/2 - (char_width_ * strlen(dialog_text))/2);
+ if (dialog_show_log) {
+ y = gr_get_height(headerIcon) + char_height_;
+ }
+ else {
+ y = (gr_fb_height()/2 + iconHeight/2);
+ }
+
+ SetColor(ERROR_TEXT);
+ gr_text(x, y, dialog_text, 0);
+ y += char_height_ + 2;
+
+ if (dialog_show_log) {
+ int cx, cy;
+ gr_set_font("log");
+ gr_font_size(&cx, &cy);
+
+ size_t row;
+ for (row = 0; row < log_text_rows_; ++row) {
+ gr_text(2, y, text_[row], 0);
+ y += cy + 2;
+ }
+ gr_set_font("menu");
+ }
+
+ if (dialog_icon == D_ERROR) {
+ /*
+ * This could be improved...
+ *
+ * Draw rect around text "Okay".
+ * Text is centered horizontally.
+ * Bottom of text is 4 lines from bottom of screen.
+ * Rect width 4px
+ * Rect padding 8px
+ */
+ w = char_width_ * 4;
+ h = char_height_;
+ x = gr_fb_width()/2 - w/2;
+ y = gr_fb_height() - h - 4 * char_height_;
+ SetColor(HEADER);
+ gr_fill(x-(4+8), y-(4+8), x+w+(4+8), y+h+(4+8));
+ SetColor(MENU_SEL_BG);
+ gr_fill(x-8, y-8, x+w+8, y+h+8);
+ SetColor(MENU_SEL_FG);
+ gr_text(x, y, "Okay", 0);
+ }
+}
+
// Redraw everything on the screen. Does not flip pages.
// Should only be called with updateMutex locked.
void ScreenRecoveryUI::draw_screen_locked() {
- if (!show_text) {
- draw_background_locked(currentIcon);
- draw_progress_locked();
- } else {
- gr_color(0, 0, 0, 255);
- gr_clear();
+ draw_background_locked(currentIcon);
- int y = 0;
- if (show_menu) {
- char recovery_fingerprint[PROPERTY_VALUE_MAX];
- property_get("ro.bootimage.build.fingerprint", recovery_fingerprint, "");
+ if (DialogShowing()) {
+ draw_dialog();
+ return;
+ }
- SetColor(INFO);
- DrawTextLine(&y, "Android Recovery", true);
- for (auto& chunk : android::base::Split(recovery_fingerprint, ":")) {
- DrawTextLine(&y, chunk.c_str(), false);
- }
- DrawTextLines(&y, HasThreeButtons() ? REGULAR_HELP : LONG_PRESS_HELP);
-
- SetColor(HEADER);
- DrawTextLines(&y, menu_headers_);
-
- SetColor(MENU);
- DrawHorizontalRule(&y);
- y += 4;
- for (int i = 0; i < menu_items; ++i) {
- if (i == menu_sel) {
- // Draw the highlight bar.
- SetColor(IsLongPress() ? MENU_SEL_BG_ACTIVE : MENU_SEL_BG);
- gr_fill(0, y - 2, gr_fb_width(), y + char_height + 2);
- // Bold white text for the selected item.
- SetColor(MENU_SEL_FG);
- gr_text(4, y, menu_[i], true);
- SetColor(MENU);
- } else {
- gr_text(4, y, menu_[i], false);
- }
- y += char_height + 4;
+ if (show_text) {
+ if (currentIcon == ERASING || currentIcon == INSTALLING_UPDATE || currentIcon == VIEWING_LOG) {
+ size_t y = currentIcon == INSTALLING_UPDATE ? gr_fb_height() / 4 : header_height_ + 4;
+
+ SetColor(LOG);
+ int cx, cy;
+ gr_set_font("log");
+ gr_font_size(&cx, &cy);
+ // display from the bottom up, until we hit the top of the
+ // screen or we've displayed the entire text buffer.
+ size_t ty, count;
+ int row = (text_first_row_ + log_text_rows_ - 1) % log_text_rows_;
+ for (ty = gr_fb_height() - cy, count = 0;
+ ty > y + 2 && count < log_text_rows_;
+ ty -= (cy + 2), ++count) {
+ gr_text(4, ty, text_[row], 0);
+ --row;
+ if (row < 0) row = log_text_rows_ - 1;
}
- DrawHorizontalRule(&y);
+ gr_set_font("menu");
+ return;
}
- // display from the bottom up, until we hit the top of the
- // screen, the bottom of the menu, or we've displayed the
- // entire text buffer.
- SetColor(LOG);
- int row = (text_top_ + text_rows_ - 1) % text_rows_;
- size_t count = 0;
- for (int ty = gr_fb_height() - char_height;
- ty >= y && count < text_rows_;
- ty -= char_height, ++count) {
- gr_text(0, ty, text_[row], false);
- --row;
- if (row < 0) row = text_rows_ - 1;
+ if (show_menu) {
+ int i, y;
+ draw_header_icon();
+ draw_sysbar();
+
+ // Divider
+ y = text_first_row_ * char_height_;
+ SetColor(MENU_SEL_FG);
+ gr_fill(0, y - 1, gr_fb_width(), y);
+
+ if (header_items > 0) {
+ for (i = 0; i < header_items; ++i) {
+ draw_menu_item(text_first_row_ + 3*i,
+ menu_headers_[i], false);
+ }
+ y = (text_first_row_ + 3*header_items) * char_height_;
+ SetColor(MENU_SEL_FG);
+ gr_fill(0, y - 1, gr_fb_width(), y);
+ }
+ int nr_items = menu_items - menu_show_start_;
+ if (header_items + nr_items > max_menu_rows_)
+ nr_items = max_menu_rows_ - header_items;
+ for (i = 0; i < nr_items; ++i) {
+ const char* text = menu_[menu_show_start_ + i];
+ draw_menu_item(text_first_row_ + 3 * (header_items + i),
+ menu_[menu_show_start_ + i],
+ ((menu_show_start_ + i) == menu_sel));
+ }
}
}
}
@@ -297,20 +453,9 @@ void ScreenRecoveryUI::draw_screen_locked() {
// Redraw everything on the screen and flip the screen (make it visible).
// Should only be called with updateMutex locked.
void ScreenRecoveryUI::update_screen_locked() {
- draw_screen_locked();
- gr_flip();
-}
-
-// Updates only the progress bar, if possible, otherwise redraws the screen.
-// Should only be called with updateMutex locked.
-void ScreenRecoveryUI::update_progress_locked() {
- if (show_text || !pagesIdentical) {
- draw_screen_locked(); // Must redraw the whole screen
- pagesIdentical = true;
- } else {
- draw_progress_locked(); // Draw only the progress bar and overlays
- }
- gr_flip();
+ update_waiting = true;
+ pthread_cond_signal(&progressCondition);
+ LOGV("%s: %p\n", __func__, __builtin_return_address(0));
}
// Keeps the progress bar updated, even when the process is otherwise busy.
@@ -319,20 +464,31 @@ void* ScreenRecoveryUI::ProgressThreadStartRoutine(void* data) {
return nullptr;
}
+void ScreenRecoveryUI::OMGRainbows()
+{
+ rainbow = rainbow ? false : true;
+ set_rainbow_mode(rainbow);
+ property_set("sys.rainbow.recovery", rainbow ? "1" : "0");
+}
+
void ScreenRecoveryUI::ProgressThreadLoop() {
double interval = 1.0 / animation_fps;
while (true) {
- double start = now();
pthread_mutex_lock(&updateMutex);
+ if (progressBarType == EMPTY && !update_waiting)
+ pthread_cond_wait(&progressCondition, &updateMutex);
- int redraw = 0;
+ bool redraw = false;
+ double start = now();
+
+ LOGV("loop %f show_text=%d progressBarType=%d waiting=%d\n", start, show_text, progressBarType, update_waiting );
// update the installation animation, if active
// skip this if we have a text overlay (too expensive to update)
if ((currentIcon == INSTALLING_UPDATE || currentIcon == ERASING) &&
- installing_frames > 0 && !show_text) {
+ installing_frames > 0) {
installingFrame = (installingFrame + 1) % installing_frames;
- redraw = 1;
+ redraw = true;
}
// move the progress bar forward on timed intervals, if configured
@@ -343,13 +499,26 @@ void ScreenRecoveryUI::ProgressThreadLoop() {
if (p > 1.0) p = 1.0;
if (p > progress) {
progress = p;
- redraw = 1;
+ redraw = true;
}
}
- if (redraw) update_progress_locked();
+ if (update_waiting || !pagesIdentical) {
+ LOGV("call draw_screen_locked\n");
+ draw_screen_locked();
+ if (!update_waiting)
+ pagesIdentical = true;
+ }
+ if (redraw) {
+ LOGV("call draw_progress_locked\n");
+ draw_progress_locked();
+ }
+ gr_flip();
+
+ update_waiting = false;
pthread_mutex_unlock(&updateMutex);
+
double end = now();
// minimum of 20ms delay between frames
double delay = interval - (end-start);
@@ -391,23 +560,47 @@ static char** Alloc2d(size_t rows, size_t cols) {
void ScreenRecoveryUI::Init() {
gr_init();
- gr_font_size(&char_width, &char_height);
- text_rows_ = gr_fb_height() / char_height;
- text_cols_ = gr_fb_width() / char_width;
+ gr_set_font("log");
+ gr_font_size(&log_char_width_, &log_char_height_);
+ gr_set_font("menu");
+ gr_font_size(&char_width_, &char_height_);
+
+ text_col_ = text_row_ = 0;
+ text_top_ = 1;
+
+ LoadBitmap("icon_header", &headerIcon);
+ LoadBitmap("icon_sysbar_back", &sysbarBackIcon);
+ LoadBitmap("icon_sysbar_back_highlight", &sysbarBackHighlightIcon);
+ LoadBitmap("icon_sysbar_home", &sysbarHomeIcon);
+ LoadBitmap("icon_sysbar_home_highlight", &sysbarHomeHighlightIcon);
+
+ header_height_ = gr_get_height(headerIcon);
+ header_width_ = gr_get_width(headerIcon);
+
+ sysbar_height_ = gr_get_height(sysbarBackIcon);
- text_ = Alloc2d(text_rows_, text_cols_ + 1);
+ text_rows_ = (gr_fb_height() - sysbar_height_) / char_height_;
+ text_cols_ = gr_fb_width() / char_width_;
+
+ log_text_rows_ = (gr_fb_height() - sysbar_height_) / log_char_height_;
+ log_text_cols_ = gr_fb_width() / log_char_width_;
+
+ text_ = Alloc2d(log_text_rows_, log_text_cols_ + 1);
file_viewer_text_ = Alloc2d(text_rows_, text_cols_ + 1);
menu_ = Alloc2d(text_rows_, text_cols_ + 1);
- text_col_ = text_row_ = 0;
- text_top_ = 1;
+ text_first_row_ = (header_height_ / char_height_) + 1;
+ menu_item_start_ = text_first_row_ * char_height_;
+ max_menu_rows_ = (text_rows_ - text_first_row_) / 3;
backgroundIcon[NONE] = nullptr;
LoadBitmapArray("icon_installing", &installing_frames, &installation);
backgroundIcon[INSTALLING_UPDATE] = installing_frames ? installation[0] : nullptr;
backgroundIcon[ERASING] = backgroundIcon[INSTALLING_UPDATE];
- LoadBitmap("icon_error", &backgroundIcon[ERROR]);
- backgroundIcon[NO_COMMAND] = backgroundIcon[ERROR];
+ LoadBitmap("icon_info", &backgroundIcon[D_INFO]);
+ LoadBitmap("icon_error", &backgroundIcon[D_ERROR]);
+ backgroundIcon[NO_COMMAND] = backgroundIcon[D_ERROR];
+ LoadBitmap("icon_headless", &backgroundIcon[HEADLESS]);
LoadBitmap("progress_empty", &progressBarEmpty);
LoadBitmap("progress_fill", &progressBarFill);
@@ -417,7 +610,7 @@ void ScreenRecoveryUI::Init() {
LoadLocalizedBitmap("installing_text", &backgroundText[INSTALLING_UPDATE]);
LoadLocalizedBitmap("erasing_text", &backgroundText[ERASING]);
LoadLocalizedBitmap("no_command_text", &backgroundText[NO_COMMAND]);
- LoadLocalizedBitmap("error_text", &backgroundText[ERROR]);
+ LoadLocalizedBitmap("error_text", &backgroundText[D_ERROR]);
pthread_create(&progress_thread_, nullptr, ProgressThreadStartRoutine, this);
@@ -467,7 +660,8 @@ void ScreenRecoveryUI::SetProgressType(ProgressType type) {
progressScopeStart = 0;
progressScopeSize = 0;
progress = 0;
- update_progress_locked();
+
+ update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
@@ -479,7 +673,8 @@ void ScreenRecoveryUI::ShowProgress(float portion, float seconds) {
progressScopeTime = now();
progressScopeDuration = seconds;
progress = 0;
- update_progress_locked();
+
+ update_screen_locked();
pthread_mutex_unlock(&updateMutex);
}
@@ -493,7 +688,7 @@ void ScreenRecoveryUI::SetProgress(float fraction) {
float scale = width * progressScopeSize;
if ((int) (progress * scale) != (int) (fraction * scale)) {
progress = fraction;
- update_progress_locked();
+ update_screen_locked();
}
}
pthread_mutex_unlock(&updateMutex);
@@ -506,23 +701,22 @@ void ScreenRecoveryUI::SetStage(int current, int max) {
pthread_mutex_unlock(&updateMutex);
}
-void ScreenRecoveryUI::Print(const char *fmt, ...) {
- char buf[256];
- va_list ap;
- va_start(ap, fmt);
- vsnprintf(buf, 256, fmt, ap);
- va_end(ap);
+void ScreenRecoveryUI::PrintV(const char* fmt, bool copy_to_stdout, va_list ap) {
+ std::string str;
+ android::base::StringAppendV(&str, fmt, ap);
- fputs(buf, stdout);
+ if (copy_to_stdout) {
+ fputs(str.c_str(), stdout);
+ }
pthread_mutex_lock(&updateMutex);
- if (text_rows_ > 0 && text_cols_ > 0) {
- for (const char* ptr = buf; *ptr != '\0'; ++ptr) {
- if (*ptr == '\n' || text_col_ >= text_cols_) {
+ if (log_text_rows_ > 0 && log_text_cols_ > 0) {
+ for (const char* ptr = str.c_str(); *ptr != '\0'; ++ptr) {
+ if (*ptr == '\n' || text_col_ >= log_text_cols_) {
text_[text_row_][text_col_] = '\0';
text_col_ = 0;
- text_row_ = (text_row_ + 1) % text_rows_;
- if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % text_rows_;
+ text_row_ = (text_row_ + 1) % log_text_rows_;
+ if (text_row_ == text_top_) text_top_ = (text_top_ + 1) % log_text_rows_;
}
if (*ptr != '\n') text_[text_row_][text_col_++] = *ptr;
}
@@ -532,6 +726,20 @@ void ScreenRecoveryUI::Print(const char *fmt, ...) {
pthread_mutex_unlock(&updateMutex);
}
+void ScreenRecoveryUI::Print(const char* fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ PrintV(fmt, true, ap);
+ va_end(ap);
+}
+
+void ScreenRecoveryUI::PrintOnScreenOnly(const char *fmt, ...) {
+ va_list ap;
+ va_start(ap, fmt);
+ PrintV(fmt, false, ap);
+ va_end(ap);
+}
+
void ScreenRecoveryUI::PutChar(char ch) {
pthread_mutex_lock(&updateMutex);
if (ch != '\n') text_[text_row_][text_col_++] = ch;
@@ -549,8 +757,8 @@ void ScreenRecoveryUI::ClearText() {
text_col_ = 0;
text_row_ = 0;
text_top_ = 1;
- for (size_t i = 0; i < text_rows_; ++i) {
- memset(text_[i], 0, text_cols_ + 1);
+ for (size_t i = 0; i < log_text_rows_; ++i) {
+ memset(text_[i], 0, log_text_cols_ + 1);
}
pthread_mutex_unlock(&updateMutex);
}
@@ -560,13 +768,15 @@ void ScreenRecoveryUI::ShowFile(FILE* fp) {
offsets.push_back(ftell(fp));
ClearText();
+ SetBackground(RecoveryUI::VIEWING_LOG);
+
struct stat sb;
fstat(fileno(fp), &sb);
bool show_prompt = false;
while (true) {
if (show_prompt) {
- Print("--(%d%% of %d bytes)--",
+ PrintOnScreenOnly("--(%d%% of %d bytes)--",
static_cast<int>(100 * (double(ftell(fp)) / double(sb.st_size))),
static_cast<int>(sb.st_size));
Redraw();
@@ -630,11 +840,82 @@ void ScreenRecoveryUI::ShowFile(const char* filename) {
text_top_ = old_text_top;
}
+void ScreenRecoveryUI::DialogShowInfo(const char* text)
+{
+ pthread_mutex_lock(&updateMutex);
+ free(dialog_text);
+ dialog_text = strdup(text);
+ dialog_show_log = false;
+ dialog_icon = D_INFO;
+ update_screen_locked();
+ pthread_mutex_unlock(&updateMutex);
+}
+
+void ScreenRecoveryUI::DialogShowError(const char* text)
+{
+ pthread_mutex_lock(&updateMutex);
+ free(dialog_text);
+ dialog_text = strdup(text);
+ dialog_show_log = false;
+ dialog_icon = D_ERROR;
+ update_screen_locked();
+ pthread_mutex_unlock(&updateMutex);
+}
+
+void ScreenRecoveryUI::DialogShowErrorLog(const char* text)
+{
+ pthread_mutex_lock(&updateMutex);
+ free(dialog_text);
+ dialog_text = strdup(text);
+ dialog_show_log = true;
+ dialog_icon = D_ERROR;
+ update_screen_locked();
+ pthread_mutex_unlock(&updateMutex);
+}
+
+void ScreenRecoveryUI::DialogDismiss()
+{
+ pthread_mutex_lock(&updateMutex);
+ free(dialog_text);
+ dialog_text = NULL;
+ update_screen_locked();
+ pthread_mutex_unlock(&updateMutex);
+}
+
+void ScreenRecoveryUI::SetHeadlessMode()
+{
+ pthread_mutex_lock(&updateMutex);
+ free(dialog_text);
+ dialog_text = strdup("");
+ dialog_show_log = false;
+ dialog_icon = HEADLESS;
+ update_screen_locked();
+ pthread_mutex_unlock(&updateMutex);
+}
+
+void ScreenRecoveryUI::SetSysbarState(int state)
+{
+ if (HasBackKey()) {
+ state &= ~SYSBAR_BACK;
+ }
+ if (HasHomeKey()) {
+ state &= ~SYSBAR_HOME;
+ }
+ sysbar_state = state;
+ Redraw();
+}
+
void ScreenRecoveryUI::StartMenu(const char* const * headers, const char* const * items,
int initial_selection) {
pthread_mutex_lock(&updateMutex);
if (text_rows_ > 0 && text_cols_ > 0) {
+ header_items = 0;
menu_headers_ = headers;
+ if (menu_headers_) {
+ while (menu_headers_[header_items]) {
+ ++header_items;
+ }
+ }
size_t i = 0;
for (; i < text_rows_ && items[i] != nullptr; ++i) {
strncpy(menu_[i], items[i], text_cols_ - 1);
@@ -643,22 +924,59 @@ void ScreenRecoveryUI::StartMenu(const char* const * headers, const char* const
menu_items = i;
show_menu = true;
menu_sel = initial_selection;
+ if (menu_show_start_ <= menu_sel - max_menu_rows_ ||
+ menu_show_start_ > menu_sel) {
+ menu_show_start_ = menu_sel;
+ }
update_screen_locked();
}
pthread_mutex_unlock(&updateMutex);
}
-int ScreenRecoveryUI::SelectMenu(int sel) {
+int ScreenRecoveryUI::SelectMenu(int sel, bool abs /* = false */) {
+ int wrapped = 0;
pthread_mutex_lock(&updateMutex);
+ if (abs) {
+ sel += menu_show_start_ - header_items;
+ }
if (show_menu) {
int old_sel = menu_sel;
menu_sel = sel;
// Wrap at top and bottom.
- if (menu_sel < 0) menu_sel = menu_items - 1;
- if (menu_sel >= menu_items) menu_sel = 0;
-
+ if (rainbow) {
+ if (menu_sel > old_sel) {
+ move_rainbow(1);
+ } else if (menu_sel < old_sel) {
+ move_rainbow(-1);
+ }
+ }
+ if (menu_sel < 0) {
+ wrapped = -1;
+ menu_sel = menu_items + menu_sel;
+ }
+ if (menu_sel >= menu_items) {
+ wrapped = 1;
+ menu_sel = menu_sel - menu_items;
+ }
+ if (menu_sel < menu_show_start_ && menu_show_start_ > 0) {
+ menu_show_start_ = menu_sel;
+ }
+ if (menu_sel - menu_show_start_ >= max_menu_rows_ - header_items) {
+ menu_show_start_ = menu_sel - (max_menu_rows_ - header_items) + 1;
+ }
sel = menu_sel;
+ if (wrapped != 0) {
+ if (wrap_count / wrapped > 0) {
+ wrap_count += wrapped;
+ } else {
+ wrap_count = wrapped;
+ }
+ if (wrap_count / wrapped >= 5) {
+ wrap_count = 0;
+ OMGRainbows();
+ }
+ }
if (menu_sel != old_sel) update_screen_locked();
}
pthread_mutex_unlock(&updateMutex);
@@ -669,7 +987,6 @@ void ScreenRecoveryUI::EndMenu() {
pthread_mutex_lock(&updateMutex);
if (show_menu && text_rows_ > 0 && text_cols_ > 0) {
show_menu = false;
- update_screen_locked();
}
pthread_mutex_unlock(&updateMutex);
}