diff --git a/software/userinterface/editor.cc b/software/userinterface/editor.cc index 5e0350d22..ed0ca625c 100644 --- a/software/userinterface/editor.cc +++ b/software/userinterface/editor.cc @@ -124,20 +124,26 @@ void Editor :: init(Screen *scr, Keyboard *key) void Editor :: draw(void) { - struct Line line; + struct Line line, *line_ptr; int width = window->get_size_x(); for(int i=0;imove_cursor(0, i); - line = (*text)[i + first_line]; + int line_idx = i + first_line; + line = (*text)[line_idx]; if (line.buffer) { - window->output_length(line.buffer, line.length); - window->repeat(' ', width - line.length); + draw(line_idx, &line); } else { window->repeat(' ', width); } } } +void Editor :: draw(int line_idx, Line *line) +{ + window->output_length(line->buffer, line->length); + window->repeat(' ', window->get_size_x() - line->length); +} + void Editor :: deinit() { if(window) @@ -182,7 +188,7 @@ int Editor :: handle_key(uint8_t c) draw(); } break; - case KEY_F1: // F1 -> page up + case KEY_F1: // page up case KEY_PAGEUP: first_line -= height + 1; if (first_line < 0) { @@ -190,7 +196,12 @@ int Editor :: handle_key(uint8_t c) } draw(); break; - case KEY_F7: // F7 -> page down + case KEY_F2: // start + case KEY_HOME: + first_line = 0; + draw(); + break; + case KEY_F7: // page down case KEY_PAGEDOWN: first_line += height - 1; if (first_line >= linecount - height) { @@ -200,6 +211,11 @@ int Editor :: handle_key(uint8_t c) } draw(); break; + case KEY_F8: // end + case KEY_END: + first_line = linecount - height; + draw(); + break; case KEY_BACK: // backspace break; case KEY_SPACE: // space diff --git a/software/userinterface/editor.h b/software/userinterface/editor.h index 1a43ef3ce..3817867f1 100644 --- a/software/userinterface/editor.h +++ b/software/userinterface/editor.h @@ -13,8 +13,6 @@ class UserInterface; class Editor : public UIObject { UserInterface *user_interface; - void line_breakdown(const char *text_buffer, int buffer_size); - void draw(); public: int line_length; int height; @@ -34,8 +32,20 @@ class Editor : public UIObject virtual void init(Screen *win, Keyboard *k); virtual void deinit(void); + virtual void line_breakdown(const char *text_buffer, int buffer_size); + virtual void draw(); + virtual void draw(int line_idx, Line *line); virtual int poll(int); virtual int handle_key(uint8_t); }; +class HexEditor : public Editor +{ + UserInterface *user_interface; + void line_breakdown(const char *text_buffer, int buffer_size); + void draw(int line_idx, Line *line); +public: + HexEditor(UserInterface *ui, const char *text_buffer, int max_len); +}; + #endif diff --git a/software/userinterface/hex_editor.cc b/software/userinterface/hex_editor.cc new file mode 100644 index 000000000..df1bbce11 --- /dev/null +++ b/software/userinterface/hex_editor.cc @@ -0,0 +1,57 @@ +#include "editor.h" +#include +#include + +static const char hex_chars[] = "0123456789ABCDEF"; + +HexEditor :: HexEditor(UserInterface *ui, const char *text_buffer, int max_len) : Editor(ui, text_buffer, max_len) +{ +} + +void HexEditor :: line_breakdown(const char *text_buffer, int buffer_size) +{ + Line current; + int pos = 0; + linecount = 0; + + text->clear_list(); + while (pos < buffer_size) { + current.buffer = text_buffer + pos; + current.length = (buffer_size - pos > BYTES_PER_HEX_ROW) ? BYTES_PER_HEX_ROW : buffer_size - pos;; + text->append(current); + pos += current.length; + linecount++; + } +} + +inline void add_hex_byte(char *buf, int offset, uint8_t byte) +{ + buf[offset] = hex_chars[(byte >> 4) & 0x0F]; + buf[offset + 1] = hex_chars[byte & 0x0F]; +} + +inline void add_hex_word(char *buf, int offset, uint16_t word) +{ + add_hex_byte(buf, offset, (word >> 8) & 0xFF); + add_hex_byte(buf, offset + 2, word & 0xFF); +} + +void HexEditor :: draw(int line_idx, Line *line) +{ + #define HEX_COL_START 5 + #define TXT_COL_START (HEX_COL_START + (3 * BYTES_PER_HEX_ROW)) + + char hex_buf[CHARS_PER_HEX_ROW]; + memset(hex_buf, ' ', CHARS_PER_HEX_ROW); + add_hex_word(hex_buf, 0, line_idx * BYTES_PER_HEX_ROW); + + for (int i = 0; i < line->length; i++) { + uint8_t c = (uint8_t) line->buffer[i]; + add_hex_byte(hex_buf, HEX_COL_START + (3 * i), c); + // represent all non-printable characters as '.' based on the character set used by firmware version 3.10j + hex_buf[TXT_COL_START + i] = (char) ((c == 0 || c == 8 || c == 10 || c == 13 || (c >=20 && c <= 31) || (c >= 144 && c <= 159)) ? '.' : c); + } + + window->output_length(hex_buf, CHARS_PER_HEX_ROW); + window->repeat(' ', window->get_size_x() - CHARS_PER_HEX_ROW); +} diff --git a/software/userinterface/user_file_interaction.cc b/software/userinterface/user_file_interaction.cc index bdb22b2a8..9f25d9862 100644 --- a/software/userinterface/user_file_interaction.cc +++ b/software/userinterface/user_file_interaction.cc @@ -13,6 +13,9 @@ #include "home_directory.h" #include "subsys.h" +#include "editor.h" + +#define MAX_FILE_SIZE_TO_VIEW 262144 // member int UserFileInteraction::fetch_context_items(BrowsableDirEntry *br, IndexedList &list) @@ -30,9 +33,10 @@ int UserFileInteraction::fetch_context_items(BrowsableDirEntry *br, IndexedList< list.append(new Action("Enter", UserFileInteraction::S_enter, 0)); count++; } - if ((info->size <= 262144) && (!(info->attrib & AM_DIR))) { + if ((info->size <= MAX_FILE_SIZE_TO_VIEW) && (!(info->attrib & AM_DIR))) { list.append(new Action("View", UserFileInteraction::S_view, 0)); - count++; + list.append(new Action("Hex View", UserFileInteraction::S_hex_view, 0)); + count += 2; } if (info->is_writable()) { list.append(new Action("Rename", UserFileInteraction::S_rename, 0)); @@ -131,7 +135,7 @@ int UserFileInteraction::S_delete(SubsysCommand *cmd) return 0; } -int UserFileInteraction::S_view(SubsysCommand *cmd) +int _view(SubsysCommand *cmd, EditorType editor_type) { FileManager *fm = FileManager::getFileManager(); File *f = 0; @@ -141,14 +145,31 @@ int UserFileInteraction::S_view(SubsysCommand *cmd) uint32_t size = f->get_size(); char *text_buf = new char[size + 1]; FRESULT fres = f->read(text_buf, size, &transferred); - printf("Res = %d. Read text buffer: %d bytes\n", fres, transferred); + printf("Res = %d. Read text buffer: %d bytes. File size: %d bytes\n", fres, transferred, size); text_buf[transferred] = 0; - cmd->user_interface->run_editor(text_buf, transferred); + switch (editor_type) { + case HEX_EDITOR: + cmd->user_interface->run_hex_editor(text_buf, transferred); + break; + default: + cmd->user_interface->run_editor(text_buf, transferred); + break; + } delete text_buf; } return 0; } +int UserFileInteraction::S_view(SubsysCommand *cmd) +{ + return _view(cmd, TEXT_EDITOR); +} + +int UserFileInteraction::S_hex_view(SubsysCommand *cmd) +{ + return _view(cmd, HEX_EDITOR); +} + int UserFileInteraction::S_createDir(SubsysCommand *cmd) { char buffer[64]; diff --git a/software/userinterface/user_file_interaction.h b/software/userinterface/user_file_interaction.h index bf7e6bf81..3119deec7 100644 --- a/software/userinterface/user_file_interaction.h +++ b/software/userinterface/user_file_interaction.h @@ -13,6 +13,8 @@ #include "subsys.h" #include "filemanager.h" +enum EditorType { TEXT_EDITOR, HEX_EDITOR}; + class Path; class Action; class BrowsableDirEntry; @@ -26,6 +28,7 @@ class UserFileInteraction : public SubSystem, ObjectWithMenu { static int S_rename(SubsysCommand *cmd); static int S_delete(SubsysCommand *cmd); static int S_view(SubsysCommand *cmd); + static int S_hex_view(SubsysCommand *cmd); static int S_createDir(SubsysCommand *cmd); static int S_runApp(SubsysCommand *cmd); diff --git a/software/userinterface/userinterface.cc b/software/userinterface/userinterface.cc index faa02717b..0ea64a36e 100644 --- a/software/userinterface/userinterface.cc +++ b/software/userinterface/userinterface.cc @@ -383,15 +383,24 @@ void UserInterface :: hide_progress(void) delete status_box; } -void UserInterface :: run_editor(const char *text_buf, int max_len) +void UserInterface :: run_editor(Editor *editor) { - Editor *edit = new Editor(this, text_buf, max_len); - edit->init(screen, keyboard); + editor->init(screen, keyboard); int ret; do { - ret = edit->poll(0); + ret = editor->poll(0); } while(!ret); - edit->deinit(); + editor->deinit(); +} + +void UserInterface :: run_editor(const char *text_buf, int max_len) +{ + run_editor(new Editor(this, text_buf, max_len)); +} + +void UserInterface :: run_hex_editor(const char *text_buf, int max_len) +{ + run_editor(new HexEditor(this, text_buf, max_len)); } int UserInterface :: enterSelection() diff --git a/software/userinterface/userinterface.h b/software/userinterface/userinterface.h index e7c14bc4d..0eeb1b212 100644 --- a/software/userinterface/userinterface.h +++ b/software/userinterface/userinterface.h @@ -28,6 +28,11 @@ #define CFG_USERIF_ULTICOPY_NAME 0x0B #define CFG_USERIF_FILENAME_OVERFLOW_SQUEEZE 0x0C +#define BYTES_PER_HEX_ROW 8 +#define CHARS_PER_HEX_ROW 37 + +class Editor; +class HexEditor; class UserInterface : public ConfigurableObject, public HostClient { private: @@ -45,6 +50,8 @@ class UserInterface : public ConfigurableObject, public HostClient void set_screen_title(void); bool pollFocussed(void); bool buttonDownFor(uint32_t ms); + void run_editor(Editor *); + UIStatusBox *status_box; public: int color_border, color_bg, color_fg, color_sel, color_sel_bg, config_save, filename_overflow_squeeze; @@ -83,6 +90,7 @@ class UserInterface : public ConfigurableObject, public HostClient int getPreferredType(void); void run_editor(const char *, int); + void run_hex_editor(const char *, int); void swapDisk(void); UIObject *get_root_object(void) { return ui_objects[0]; } diff --git a/target/u64/nios2/ultimate/Makefile b/target/u64/nios2/ultimate/Makefile index a3769e025..ba6344ad9 100755 --- a/target/u64/nios2/ultimate/Makefile +++ b/target/u64/nios2/ultimate/Makefile @@ -89,6 +89,7 @@ SRCS_CC = u2p_init.cc \ ui_elements.cc \ user_file_interaction.cc \ editor.cc \ + hex_editor.cc \ tree_browser.cc \ tree_browser_state.cc \ config_menu.cc \