Merge "Rewritten file pager."
This commit is contained in:
+86
-68
@@ -28,6 +28,8 @@
|
|||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
#include "common.h"
|
#include "common.h"
|
||||||
#include "device.h"
|
#include "device.h"
|
||||||
#include "minui/minui.h"
|
#include "minui/minui.h"
|
||||||
@@ -203,6 +205,13 @@ void ScreenRecoveryUI::SetColor(UIElement e) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScreenRecoveryUI::DrawHorizontalRule(int* y) {
|
||||||
|
SetColor(MENU);
|
||||||
|
*y += 4;
|
||||||
|
gr_fill(0, *y, gr_fb_width(), *y + 2);
|
||||||
|
*y += 8;
|
||||||
|
}
|
||||||
|
|
||||||
// Redraw everything on the screen. Does not flip pages.
|
// Redraw everything on the screen. Does not flip pages.
|
||||||
// Should only be called with updateMutex locked.
|
// Should only be called with updateMutex locked.
|
||||||
void ScreenRecoveryUI::draw_screen_locked() {
|
void ScreenRecoveryUI::draw_screen_locked() {
|
||||||
@@ -214,12 +223,11 @@ void ScreenRecoveryUI::draw_screen_locked() {
|
|||||||
gr_clear();
|
gr_clear();
|
||||||
|
|
||||||
int y = 0;
|
int y = 0;
|
||||||
int i = 0;
|
|
||||||
if (show_menu) {
|
if (show_menu) {
|
||||||
SetColor(HEADER);
|
SetColor(HEADER);
|
||||||
|
|
||||||
for (; i < menu_top + menu_items; ++i) {
|
for (int i = 0; i < menu_top + menu_items; ++i) {
|
||||||
if (i == menu_top) SetColor(MENU);
|
if (i == menu_top) DrawHorizontalRule(&y);
|
||||||
|
|
||||||
if (i == menu_top + menu_sel) {
|
if (i == menu_top + menu_sel) {
|
||||||
// draw the highlight bar
|
// draw the highlight bar
|
||||||
@@ -234,11 +242,8 @@ void ScreenRecoveryUI::draw_screen_locked() {
|
|||||||
}
|
}
|
||||||
y += char_height+4;
|
y += char_height+4;
|
||||||
}
|
}
|
||||||
SetColor(MENU);
|
|
||||||
y += 4;
|
DrawHorizontalRule(&y);
|
||||||
gr_fill(0, y, gr_fb_width(), y+2);
|
|
||||||
y += 4;
|
|
||||||
++i;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SetColor(LOG);
|
SetColor(LOG);
|
||||||
@@ -249,7 +254,7 @@ void ScreenRecoveryUI::draw_screen_locked() {
|
|||||||
int row = (text_top+text_rows-1) % text_rows;
|
int row = (text_top+text_rows-1) % text_rows;
|
||||||
size_t count = 0;
|
size_t count = 0;
|
||||||
for (int ty = gr_fb_height() - char_height;
|
for (int ty = gr_fb_height() - char_height;
|
||||||
ty > y+2 && count < text_rows;
|
ty >= y && count < text_rows;
|
||||||
ty -= char_height, ++count) {
|
ty -= char_height, ++count) {
|
||||||
gr_text(0, ty, text[row], 0);
|
gr_text(0, ty, text[row], 0);
|
||||||
--row;
|
--row;
|
||||||
@@ -495,72 +500,85 @@ void ScreenRecoveryUI::Print(const char *fmt, ...) {
|
|||||||
pthread_mutex_unlock(&updateMutex);
|
pthread_mutex_unlock(&updateMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: replace this with something not line-based so we can wrap correctly without getting
|
void ScreenRecoveryUI::PutChar(char ch) {
|
||||||
// confused about what line we're on.
|
|
||||||
void ScreenRecoveryUI::print_no_update(const char* s) {
|
|
||||||
pthread_mutex_lock(&updateMutex);
|
pthread_mutex_lock(&updateMutex);
|
||||||
if (text_rows > 0 && text_cols > 0) {
|
if (ch != '\n') text[text_row][text_col++] = ch;
|
||||||
for (const char* ptr = s; *ptr != '\0'; ++ptr) {
|
if (ch == '\n' || text_col >= text_cols) {
|
||||||
if (*ptr == '\n' || text_col >= text_cols) {
|
text_col = 0;
|
||||||
text[text_row][text_col] = '\0';
|
++text_row;
|
||||||
text_col = 0;
|
|
||||||
text_row = (text_row + 1) % text_rows;
|
|
||||||
if (text_row == text_top) text_top = (text_top + 1) % text_rows;
|
|
||||||
}
|
|
||||||
if (*ptr != '\n') text[text_row][text_col++] = *ptr;
|
|
||||||
}
|
|
||||||
text[text_row][text_col] = '\0';
|
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&updateMutex);
|
pthread_mutex_unlock(&updateMutex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ScreenRecoveryUI::ClearText() {
|
||||||
|
pthread_mutex_lock(&updateMutex);
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
pthread_mutex_unlock(&updateMutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ScreenRecoveryUI::ShowFile(FILE* fp) {
|
||||||
|
std::vector<long> offsets;
|
||||||
|
offsets.push_back(ftell(fp));
|
||||||
|
ClearText();
|
||||||
|
|
||||||
|
struct stat sb;
|
||||||
|
fstat(fileno(fp), &sb);
|
||||||
|
|
||||||
|
bool show_prompt = false;
|
||||||
|
while (true) {
|
||||||
|
if (show_prompt) {
|
||||||
|
Print("--(%d%% of %d bytes)--",
|
||||||
|
static_cast<int>(100 * (double(ftell(fp)) / double(sb.st_size))),
|
||||||
|
static_cast<int>(sb.st_size));
|
||||||
|
Redraw();
|
||||||
|
while (show_prompt) {
|
||||||
|
show_prompt = false;
|
||||||
|
int key = WaitKey();
|
||||||
|
if (key == KEY_POWER) {
|
||||||
|
return;
|
||||||
|
} else if (key == KEY_UP || key == KEY_VOLUMEUP) {
|
||||||
|
if (offsets.size() <= 1) {
|
||||||
|
show_prompt = true;
|
||||||
|
} else {
|
||||||
|
offsets.pop_back();
|
||||||
|
fseek(fp, offsets.back(), SEEK_SET);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (feof(fp)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
offsets.push_back(ftell(fp));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClearText();
|
||||||
|
}
|
||||||
|
|
||||||
|
int ch = getc(fp);
|
||||||
|
if (ch == EOF) {
|
||||||
|
text_row = text_top = text_rows - 2;
|
||||||
|
show_prompt = true;
|
||||||
|
} else {
|
||||||
|
PutChar(ch);
|
||||||
|
if (text_col == 0 && text_row >= text_rows - 2) {
|
||||||
|
text_top = text_row;
|
||||||
|
show_prompt = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void ScreenRecoveryUI::ShowFile(const char* filename) {
|
void ScreenRecoveryUI::ShowFile(const char* filename) {
|
||||||
FILE* fp = fopen_path(filename, "re");
|
FILE* fp = fopen_path(filename, "re");
|
||||||
if (fp == nullptr) {
|
if (fp == nullptr) {
|
||||||
Print(" Unable to open %s: %s\n", filename, strerror(errno));
|
Print(" Unable to open %s: %s\n", filename, strerror(errno));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
ShowFile(fp);
|
||||||
char line[1024];
|
|
||||||
int ct = 0;
|
|
||||||
int key = 0;
|
|
||||||
while (fgets(line, sizeof(line), fp) != nullptr) {
|
|
||||||
print_no_update(line);
|
|
||||||
ct++;
|
|
||||||
if (ct % text_rows == 0) {
|
|
||||||
Redraw();
|
|
||||||
|
|
||||||
// give the user time to glance at the entries
|
|
||||||
key = WaitKey();
|
|
||||||
|
|
||||||
if (key == KEY_POWER) {
|
|
||||||
break;
|
|
||||||
} else if (key == KEY_VOLUMEUP) {
|
|
||||||
// Go back by seeking to the beginning and dumping ct - n
|
|
||||||
// lines. It's ugly, but this way we don't need to store
|
|
||||||
// the previous offsets. The files we're dumping here aren't
|
|
||||||
// expected to be very large.
|
|
||||||
ct -= 2 * text_rows;
|
|
||||||
if (ct < 0) {
|
|
||||||
ct = 0;
|
|
||||||
}
|
|
||||||
fseek(fp, 0, SEEK_SET);
|
|
||||||
for (int i = 0; i < ct; i++) {
|
|
||||||
fgets(line, sizeof(line), fp);
|
|
||||||
}
|
|
||||||
Print("^^^^^^^^^^\n");
|
|
||||||
} else {
|
|
||||||
// Next page.
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// If the user didn't abort, then give the user time to glance at
|
|
||||||
// the end of the log, sorry, no rewind here
|
|
||||||
if (key != KEY_POWER) {
|
|
||||||
Print("\n--END-- (press any key)\n");
|
|
||||||
WaitKey();
|
|
||||||
}
|
|
||||||
fclose(fp);
|
fclose(fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -581,7 +599,7 @@ void ScreenRecoveryUI::StartMenu(const char* const * headers, const char* const
|
|||||||
menu[i][text_cols-1] = '\0';
|
menu[i][text_cols-1] = '\0';
|
||||||
}
|
}
|
||||||
menu_items = i - menu_top;
|
menu_items = i - menu_top;
|
||||||
show_menu = 1;
|
show_menu = true;
|
||||||
menu_sel = initial_selection;
|
menu_sel = initial_selection;
|
||||||
update_screen_locked();
|
update_screen_locked();
|
||||||
}
|
}
|
||||||
@@ -590,7 +608,7 @@ void ScreenRecoveryUI::StartMenu(const char* const * headers, const char* const
|
|||||||
|
|
||||||
int ScreenRecoveryUI::SelectMenu(int sel) {
|
int ScreenRecoveryUI::SelectMenu(int sel) {
|
||||||
pthread_mutex_lock(&updateMutex);
|
pthread_mutex_lock(&updateMutex);
|
||||||
if (show_menu > 0) {
|
if (show_menu) {
|
||||||
int old_sel = menu_sel;
|
int old_sel = menu_sel;
|
||||||
menu_sel = sel;
|
menu_sel = sel;
|
||||||
|
|
||||||
@@ -607,8 +625,8 @@ int ScreenRecoveryUI::SelectMenu(int sel) {
|
|||||||
|
|
||||||
void ScreenRecoveryUI::EndMenu() {
|
void ScreenRecoveryUI::EndMenu() {
|
||||||
pthread_mutex_lock(&updateMutex);
|
pthread_mutex_lock(&updateMutex);
|
||||||
if (show_menu > 0 && text_rows > 0 && text_cols > 0) {
|
if (show_menu && text_rows > 0 && text_cols > 0) {
|
||||||
show_menu = 0;
|
show_menu = false;
|
||||||
update_screen_locked();
|
update_screen_locked();
|
||||||
}
|
}
|
||||||
pthread_mutex_unlock(&updateMutex);
|
pthread_mutex_unlock(&updateMutex);
|
||||||
|
|||||||
+6
-1
@@ -18,6 +18,7 @@
|
|||||||
#define RECOVERY_SCREEN_UI_H
|
#define RECOVERY_SCREEN_UI_H
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "ui.h"
|
#include "ui.h"
|
||||||
#include "minui/minui.h"
|
#include "minui/minui.h"
|
||||||
@@ -114,7 +115,11 @@ class ScreenRecoveryUI : public RecoveryUI {
|
|||||||
static void* progress_thread(void* cookie);
|
static void* progress_thread(void* cookie);
|
||||||
void progress_loop();
|
void progress_loop();
|
||||||
|
|
||||||
void print_no_update(const char*);
|
void ShowFile(FILE*);
|
||||||
|
void PutChar(char);
|
||||||
|
void ClearText();
|
||||||
|
|
||||||
|
void DrawHorizontalRule(int* y);
|
||||||
|
|
||||||
void LoadBitmap(const char* filename, gr_surface* surface);
|
void LoadBitmap(const char* filename, gr_surface* surface);
|
||||||
void LoadBitmapArray(const char* filename, int* frames, gr_surface** surface);
|
void LoadBitmapArray(const char* filename, int* frames, gr_surface** surface);
|
||||||
|
|||||||
Reference in New Issue
Block a user