diff --git a/examples/mdview2/Makefile b/examples/mdview2/Makefile index a2d8378..5569dce 100644 --- a/examples/mdview2/Makefile +++ b/examples/mdview2/Makefile @@ -8,7 +8,7 @@ PROJ_ROOT := $(abspath $(CURDIR)/../..) EXAMPLE := mdview2 -EXTRA_SRCS := mdview2_raw.c mdview2_help.c mdview2_table.c mdview2_enc.c mdview2_md.c mdview2_status.c mdview2_index.c +EXTRA_SRCS := mdview2_raw.c mdview2_hex.c mdview2_help.c mdview2_table.c mdview2_enc.c mdview2_md.c mdview2_status.c mdview2_index.c MEMORY := small # --max-allocs 100000: агрессивнее аллокация регистров SDCC — минус ~850 байт # кода на всём приложении (замер 2026-07-04) ценой более долгой компиляции. diff --git a/examples/mdview2/mdview2.c b/examples/mdview2/mdview2.c index 85793e4..a94cd4c 100644 --- a/examples/mdview2/mdview2.c +++ b/examples/mdview2/mdview2.c @@ -199,6 +199,9 @@ uint8_t g_view = VIEW_MD; /* extern: активный #if WITH_RAW uint8_t g_ready; /* extern: 1 когда первичный документ построен — F2 (RAW) рабочий */ static uint8_t g_raw_last = VIEW_RAW_WRAP; /* последний под-режим RAW (возврат по F2) */ +#if WITH_HEX +static uint8_t g_hex_last = VIEW_MD; /* вид, из которого вошли в HEX (возврат по F4) */ +#endif #endif uint8_t g_loading; /* extern: 1 во время index_lines() */ static uint8_t g_first_drawn; /* первый экран уже нарисован */ @@ -720,6 +723,12 @@ void progress_tick(void) * не MD-вид (иначе мелькал бы MD). Индекс при этом строится дальше (нужен * для MD-вида). */ if (g_view != VIEW_MD) { +#if WITH_HEX + if (g_view == VIEW_HEX) { /* HEX показывает оригинал — экран уже актуален */ + spinner_tick(); + return; + } +#endif if (!g_first_drawn) { raw_draw(); // render_raw_status(); @@ -845,18 +854,33 @@ static uint32_t map_off(uint32_t off, uint32_t from, uint32_t to) } /* Байт-позиция текущего вида (верх экрана) — единая «валюта» для переноса - * позиции между видами/наборами. */ + * позиции между видами/наборами. Валюта = offset АКТИВНОГО буфера; HEX живёт + * в байтах оригинала, для UTF-набора конвертируем через map_off. */ static uint32_t view_pos(void) { +#if WITH_HEX + if (g_view == VIEW_HEX) + return (g_active_doc == DOC_UTF8) + ? map_off(hex_pos(), orig_file_size, file_size) + : hex_pos(); +#endif #if WITH_RAW if (g_view != VIEW_MD) return raw_pos(); #endif return seg_off(top_line); } -/* Поставить текущий вид на байт-позицию off (после doc_switch). */ +/* Поставить текущий вид на байт-позицию off (активного буфера). */ static void view_reanchor(uint32_t off) { +#if WITH_HEX + if (g_view == VIEW_HEX) { + hex_reanchor((g_active_doc == DOC_UTF8) + ? map_off(off, file_size, orig_file_size) + : off); + return; + } +#endif #if WITH_RAW if (g_view != VIEW_MD) { raw_reanchor(off); return; } #endif @@ -893,7 +917,7 @@ static void switch_encoding(uint8_t next) doc_save_live(g_active_doc); /* сохранить текущий (позиция и т.п.) */ #if WITH_RAW uint32_t raw_save = raw_pos(); - if (g_view != VIEW_MD) + if (VIEW_IS_RAW(g_view)) /* HEX показывает оригинал — его позиция инвариантна */ raw_reanchor(0); /* прогрессивный показ нового буфера — с начала */ g_ready = 0; render_menu(); /* идёт индексация — прячем F2 */ @@ -911,7 +935,7 @@ static void switch_encoding(uint8_t next) g_utf_failed = 1; doc_load_live(g_active_doc); #if WITH_RAW - if (g_view != VIEW_MD) + if (VIEW_IS_RAW(g_view)) raw_reanchor(raw_save); /* буфер прежний — вернуть позицию RAW */ #endif return; @@ -1072,27 +1096,58 @@ int main(int argc, char **argv) show_help(); continue; } /* show_help сам перерисует */ - /* F2 — тумблер RAW ↔ MD (рабочий только после постройки документа). */ + /* F2 — тумблер RAW ↔ MD (из HEX тоже уводит в MD). + * Рабочий только после постройки документа. */ if (scan == KEY_F2) { if (!g_ready) continue; if (g_view == VIEW_MD) { g_view = g_raw_last; /* → RAW (последний под-режим) */ raw_seed_from(top_line); /* позиция из MD */ raw_screen_init(); - status_encoding(); + status_encoding(); render_menu(); - render_raw_status(); + render_raw_status(); raw_draw(); } else { - g_raw_last = g_view; /* запомнить под-режим RAW */ + uint32_t off = view_pos(); /* позиция из RAW/HEX */ + if (VIEW_IS_RAW(g_view)) + g_raw_last = g_view; /* запомнить под-режим RAW */ g_view = VIEW_MD; - top_line = line_at_off(raw_pos()); /* позиция из RAW */ + top_line = line_at_off(off); clamp_top(); render_full_status(); render_menu(); draw_viewport_from_cache(); } continue; } +#if WITH_HEX + /* F4 — тумблер HEX ↔ прежний вид (MD/RAW). */ + if (scan == KEY_F4) { + if (!g_ready) continue; + uint32_t off = view_pos(); /* позиция текущего вида */ + if (g_view == VIEW_HEX) { /* HEX → прежний вид */ + g_view = g_hex_last; + view_reanchor(off); + if (g_view == VIEW_MD) { + clamp_top(); + render_full_status(); render_menu(); + draw_viewport_from_cache(); + } else { + raw_screen_init(); + status_encoding(); render_menu(); + render_raw_status(); raw_draw(); + } + } else { /* MD/RAW → HEX */ + g_hex_last = g_view; + g_view = VIEW_HEX; + view_reanchor(off); /* active → байты оригинала */ + hex_screen_init(); + status_encoding(); render_menu(); + render_hex_status(); hex_draw(); + } + continue; + } +#endif /* цикл CP866→CP1251→KOI8R→UTF8→CP866; набор дособерётся лениво */ if (scan == KEY_F8) { uint8_t next = (g_encoding == ENC_CP866) ? ENC_CP1251 : @@ -1104,6 +1159,14 @@ int main(int argc, char **argv) if (g_abort) exit(0); /* Esc/F10 во время ленивой досборки */ /* Перерисовка — по текущему виду (switch_encoding сам не рисует). */ +#if WITH_HEX + if (g_view == VIEW_HEX) { + status_encoding(); + render_hex_status(); + hex_draw(); /* printable-колонка в новой кодировке */ + continue; + } +#endif #if WITH_RAW if (g_view != VIEW_MD) { status_encoding(); @@ -1121,6 +1184,11 @@ int main(int argc, char **argv) /* MD-режим: F1/F8/F10 здесь, навигация — в md_key() (peer к raw_key). */ md_key(scan); /* навигация MD (сама рисует+статус); незнакомые игнорит */ continue; +#if WITH_HEX + case VIEW_HEX: + hex_key(scan); /* навигация HEX (сама рисует+процент) */ + continue; +#endif #if WITH_RAW case VIEW_RAW_WRAP: case VIEW_RAW_HSCROLL: diff --git a/examples/mdview2/mdview2.h b/examples/mdview2/mdview2.h index ece41f9..8db10f1 100644 --- a/examples/mdview2/mdview2.h +++ b/examples/mdview2/mdview2.h @@ -69,6 +69,8 @@ #define VIEW_MD 0 /* markdown с форматированием (по умолчанию) */ #define VIEW_RAW_WRAP 1 /* RAW: длинные строки переносятся кратно 80 */ #define VIEW_RAW_HSCROLL 2 /* RAW: длинные строки в одну, гориз. скролл */ +#define VIEW_HEX 3 /* HEX-дамп оригинального файла */ +#define VIEW_IS_RAW(v) ((v) == VIEW_RAW_WRAP || (v) == VIEW_RAW_HSCROLL) /* ---- Кодировки --------------------------------------------------- */ /* 8-битные (CP866/CP1251/KOI8R) различаются только ремапом глифов [128-255] @@ -153,6 +155,17 @@ uint8_t raw_key(uint8_t scan); /* навигация RAW; 1 = о void raw_screen_init(void); /* очистка экрана с нужным аттрибутом */ void raw_renorm(void); /* выровнять позицию при смене под-режима (F3) */ +/* ================================================================== * + * API модуля HEX (mdview2_hex.c) — дамп ОРИГИНАЛЬНОГО файла (F4). + * Позиция hex_pos/hex_reanchor — в байтах ОРИГИНАЛА (orig_file_*); + * конвертацию в/из активного буфера делает ядро (map_off). + * ================================================================== */ +uint32_t hex_pos(void); /* offset верхнего ряда (кратен 16) */ +void hex_reanchor(uint32_t orig_off); /* поставить на ряд с байтом orig_off */ +void hex_draw(void); /* перерисовать область документа */ +uint8_t hex_key(uint8_t scan); /* навигация HEX; 1 = обработано */ +void hex_screen_init(void); /* очистка экрана */ + /* ================================================================== * * Запись директории рендер-кэша (одна на видимую строку, РОВНО 8 байт — * cache_dir_get/put адресуют сдвигом idx<<3). Контент — len пар (char,attr). @@ -189,6 +202,7 @@ void prerender_status(void); /* фикс. часть: фон, void status_encoding(void); /* только поле кодировки (col 37) */ void render_md_status_numbers(void); /* числа MD: диапазон строк + % */ void render_raw_status(void); /* RAW mode: метка режима */ +void render_hex_status(void); /* HEX mode: метка режима */ void render_full_status(void); /* encoding + numbers (MD) */ void render_menu(void); /* строка меню (по смене режима/готовности) */ uint16_t drawable_lines(void); /* число строк, готовых к показу */ @@ -278,5 +292,6 @@ uint8_t detect_encoding(void); /* автоопределени void win_rest_remap(uint8_t row, uint8_t w, uint8_t page, uint16_t off); /* вывод среза с ремапом */ void utf_convert_more(uint32_t target); /* инкрементальная конвертация до target байт */ uint8_t utf_alloc(void); /* выделить EMM-страницы под UTF-набор; 0 = нет EMM */ +uint8_t utf_cp_glyph(uint32_t cp); /* кодпойнт → один CP866-глиф ('?' без аналога) */ #endif /* MDVIEW2_H */ diff --git a/examples/mdview2/mdview2_conf.h b/examples/mdview2/mdview2_conf.h index c65ddab..330505e 100644 --- a/examples/mdview2/mdview2_conf.h +++ b/examples/mdview2/mdview2_conf.h @@ -11,6 +11,6 @@ #define MDVIEW2_CONF_H #define WITH_RAW 1 /* RAW-просмотр исходника (F2): mdview2_raw.c */ -#define WITH_HEX 0 /* HEX-просмотр (зарезервировано): mdview2_hex.c */ +#define WITH_HEX 1 /* HEX-дамп оригинального файла (F4): mdview2_hex.c */ #endif /* MDVIEW2_CONF_H */ diff --git a/examples/mdview2/mdview2_enc.c b/examples/mdview2/mdview2_enc.c index 788883a..14d0ad9 100644 --- a/examples/mdview2/mdview2_enc.c +++ b/examples/mdview2/mdview2_enc.c @@ -230,20 +230,24 @@ static const utf_sym_t utf_sym[] = { }; #define UTF_SYM_N (uint8_t)(sizeof(utf_sym) / sizeof(utf_sym[0])) -/* Кодпойнт → CP866-глиф(ы). Кириллица по таблице; спецслучаи (…, BOM) явно; - * остальные ходовые символы по таблице utf_sym[]; прочее → '?'. */ +/* Кодпойнт → ОДИН CP866-глиф: кириллица по таблице, ходовые символы по + * utf_sym[], прочее → '?'. Общая для конвертера и HEX-printable (F4). */ +uint8_t utf_cp_glyph(uint32_t cp) +{ + if (cp < 0x80) return (uint8_t)cp; + if (cp >= 0x0400 && cp <= 0x045F) return utf_cyr_to_866[cp - 0x0400]; + for (uint8_t i = 0; i < UTF_SYM_N; i++) + if (utf_sym[i].utf8 == (uint16_t)cp) return utf_sym[i].cp866; + return '?'; +} + +/* Кодпойнт → CP866-глиф(ы) в поток конвертера. Спецслучаи с НЕ-1:1 заменой + * (… → "...", BOM → ничего) здесь; остальное через utf_cp_glyph(). */ static void conv_emit_cp(uint32_t cp) { - if (cp < 0x80) { conv_put((uint8_t)cp); return; } - if (cp >= 0x0400 && cp <= 0x045F) { conv_put(utf_cyr_to_866[cp - 0x0400]); return; } if (cp == 0x2026) { conv_put('.'); conv_put('.'); conv_put('.'); return; } /* … → "..." */ if (cp == 0xFEFF) return; /* BOM/ZWNBSP — выкинуть */ - for (uint8_t i = 0; i < UTF_SYM_N; i++) - if (utf_sym[i].utf8 == (uint16_t)cp) { - conv_put(utf_sym[i].cp866); - return; - } - conv_put('?'); + conv_put(utf_cp_glyph(cp)); } /* Последовательное чтение байта ОРИГИНАЛА (utf-8) конвертером. Оригинал лежит diff --git a/examples/mdview2/mdview2_help.c b/examples/mdview2/mdview2_help.c index 5ed1ab2..cbb3184 100644 --- a/examples/mdview2/mdview2_help.c +++ b/examples/mdview2/mdview2_help.c @@ -73,7 +73,7 @@ void show_help(void) /* Содержимое (20 внутренних строк) */ uint8_t r = 0; help_line(r++, "", ATTR_HELP_BG); - help_line(r++, " MDView v1.0 (a3) -- Markdown Viewer for Sprinter", ATTR_HELP_HDR); + help_line(r++, " MDView v1.0 (b1) -- Markdown Viewer for Sprinter", ATTR_HELP_HDR); help_line(r++, " (c) 2026 \x8F\xA5\xE2\xE0\xAE\xA2 \x80\x2E\x83\x2E", ATTR_HELP_BG); help_line(r++, "", ATTR_HELP_BG); @@ -92,11 +92,11 @@ void show_help(void) help_line(r++, " Encoding and View modes:", ATTR_HELP_HDR); help_line(r++, " F2 RAW Mode", ATTR_HELP_BG); help_line(r++, " F3 Wrap/Unwrap Mode for RAW View", ATTR_HELP_BG); + help_line(r++, " F4 HEX Mode (dump of original file)", ATTR_HELP_BG); help_line(r++, " F8 Cycle CP866 / CP1251 / KOI8-R / UTF-8", ATTR_HELP_BG); help_line(r++, " Auto-detected on open; F8 to override", ATTR_HELP_BG); help_line(r++, "", ATTR_HELP_BG); help_line(r++, " File size: up to 256 KB (EMM). Lines: up to 18432.", ATTR_HELP_BG); - help_line(r++, "", ATTR_HELP_BG); (void)getkey(); diff --git a/examples/mdview2/mdview2_hex.c b/examples/mdview2/mdview2_hex.c new file mode 100644 index 0000000..c1eb72e --- /dev/null +++ b/examples/mdview2/mdview2_hex.c @@ -0,0 +1,209 @@ +/* + * mdview2_hex.c — HEX-дамп ОРИГИНАЛЬНОГО файла (F4). + * + * Показывает исходные байты файла (orig_file_phys), а не активный буфер: + * hex-дамп декодированного UTF-набора был бы искажением. Printable-колонка + * интерпретируется ТЕКУЩЕЙ кодировкой: CP866 как есть, CP1251/KOI8 через + * g_remap, UTF-8 — глиф на позиции лид-байта (continuation-байты → '.'). + * + * Формат ряда (79 колонок, один атрибут ATTR_TEXT — как RAW): + * 0x012340 │ XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX │ 16 символов + * + * Ряд выровнен на 16 байт и никогда не пересекает границу EMM-страницы + * (16 делит 16384 нацело) — один bank_read на ряд, fb()/W3-маппинг не нужны. + * Позиция (hex_top) живёт в байтах ОРИГИНАЛА; конвертацию в/из байт-позиции + * активного буфера делает ядро (view_pos/view_reanchor через map_off). + */ + +#include +#include +#include +#include +#include /* bank_read (чтение оригинала по страницам EMM) */ +#include "mdview2.h" + +#if WITH_HEX /* весь модуль опционален (mdview2_conf.h); при 0 пустой объектник */ + +#define HEX_BPR 16u /* байт на ряд */ +#define HEX_SPAN ((uint32_t)(VIEW_H - 1) * HEX_BPR) + +/* Геометрия ряда (колонки). */ +#define HX_OFF 1u /* "0x012340" */ +#define HX_SEP1 10u /* │ */ +#define HX_DUMP 12u /* пары hex-цифр */ +#define HX_SEP2 61u /* │ */ +#define HX_PRINT 63u /* printable */ + +static uint32_t hex_top; /* offset верхнего ряда (кратен 16) */ + +uint32_t hex_pos(void) { return hex_top; } + +/* Максимальный hex_top: последний ряд файла на нижней строке экрана. */ +static uint32_t hex_max_top(void) +{ + uint32_t last = (orig_file_size == 0) ? 0 + : ((orig_file_size - 1u) & ~(uint32_t)(HEX_BPR - 1u)); + return (last > HEX_SPAN) ? (last - HEX_SPAN) : 0; +} + +void hex_reanchor(uint32_t orig_off) +{ + uint32_t mt = hex_max_top(); + orig_off &= ~(uint32_t)(HEX_BPR - 1u); + hex_top = (orig_off > mt) ? mt : orig_off; +} + +void hex_screen_init(void) +{ + bios_clearwin(VIEW_TOP_ROW, 0, VIEW_H, SCREEN_W, ATTR_TEXT); +} + +/* ---- отрисовка ----------------------------------------------------- */ + +static uint8_t hexdig(uint8_t v) +{ + v &= 15u; + return (uint8_t)((v < 10u) ? ('0' + v) : ('A' - 10 + v)); +} + +/* Один байт оригинала (для UTF-lookahead за границей ряда — редкий путь). */ +static uint8_t fbo(uint32_t off) +{ + uint8_t b; + bank_read(orig_file_phys[off >> PAGE_BITS], (uint16_t)(off & PAGE_MASK), &b, 1); + return b; +} + +/* Printable-глиф для n байт ряда b[] (off — offset b[0] в файле) → out[]. */ +static void hex_print_cells(const uint8_t *b, uint32_t off, uint8_t n, uint8_t *out) +{ + for (uint8_t i = 0; i < n; i++) { + uint8_t c = b[i]; + uint8_t g; + if (c < 0x20u) { + g = '.'; + } else if (c < 0x80u || g_encoding != ENC_UTF8) { + g = (uint8_t)((c >= 0x80u && g_remap) ? g_remap[c - 0x80u] : c); + } else if ((c & 0xC0u) == 0x80u) { + g = '.'; /* continuation-байт */ + } else { + /* Лид-байт: собрать кодпойнт (хвост может выйти за ряд → fbo). + * 4-байтовые (за пределами CP866) и битые последовательности → '.'. */ + uint32_t cp; + uint8_t need, ok = 1; + if ((c & 0xE0u) == 0xC0u) { cp = (uint32_t)(c & 0x1Fu); need = 1; } + else if ((c & 0xF0u) == 0xE0u) { cp = (uint32_t)(c & 0x0Fu); need = 2; } + else { out[i] = '.'; continue; } + for (uint8_t k = 1; k <= need; k++) { + uint32_t p = off + i + k; + if (p >= orig_file_size) { ok = 0; break; } + uint8_t cb = (uint8_t)((i + k < n) ? b[i + k] : fbo(p)); + if ((cb & 0xC0u) != 0x80u) { ok = 0; break; } + cp = (cp << 6) | (uint32_t)(cb & 0x3Fu); + } + g = ok ? utf_cp_glyph(cp) : '.'; + if (g < 0x20u) g = '.'; /* overlong мог дать управляющий */ + } + out[i] = g; + } +} + +static uint8_t hex_line[SCREEN_W]; /* собранный ряд (только символы, единый attr) */ + +static void hex_draw_row(uint32_t off, uint8_t row) +{ + uint8_t buf[HEX_BPR]; + uint8_t n = 0; + + memset(hex_line, ' ', SCREEN_W); + if (off < orig_file_size) { + uint32_t rem = orig_file_size - off; + n = (rem >= HEX_BPR) ? (uint8_t)HEX_BPR : (uint8_t)rem; + bank_read(orig_file_phys[off >> PAGE_BITS], (uint16_t)(off & PAGE_MASK), buf, n); + } + if (n) { /* ряды за EOF — пустые */ + hex_line[HX_OFF] = '0'; + hex_line[HX_OFF + 1] = 'x'; + hex_line[HX_OFF + 2] = hexdig((uint8_t)(off >> 20)); + hex_line[HX_OFF + 3] = hexdig((uint8_t)(off >> 16)); + hex_line[HX_OFF + 4] = hexdig((uint8_t)(off >> 12)); + hex_line[HX_OFF + 5] = hexdig((uint8_t)(off >> 8)); + hex_line[HX_OFF + 6] = hexdig((uint8_t)(off >> 4)); + hex_line[HX_OFF + 7] = hexdig((uint8_t)off); + hex_line[HX_SEP1] = TBL_V; + for (uint8_t i = 0; i < n; i++) { + uint8_t x = (uint8_t)(HX_DUMP + i * 3u + ((i >= 8u) ? 1u : 0u)); + hex_line[x] = hexdig((uint8_t)(buf[i] >> 4)); + hex_line[x + 1] = hexdig(buf[i]); + } + hex_line[HX_SEP2] = TBL_V; + hex_print_cells(buf, off, n, hex_line + HX_PRINT); + } + bios_set_place(row, 0); + bios_write_until((const char *)hex_line, SCREEN_W, 0); +} + +void hex_draw(void) +{ + uint32_t off = hex_top; + for (uint8_t r = 0; r < VIEW_H; r++) { + hex_draw_row(off, (uint8_t)(VIEW_TOP_ROW + r)); + off += HEX_BPR; + } +} + +/* ---- статус-бар: % по байтам (как calc_raw_pct) --------------------- */ + +static uint8_t calc_hex_pct(void) +{ + return pct16((uint16_t)(hex_top >> 8), (uint16_t)(orig_file_size >> 8)); +} + +/* ---- навигация (вызывается из главного цикла при g_view == VIEW_HEX) */ + +uint8_t hex_key(uint8_t scan) +{ + uint32_t mt = hex_max_top(); + switch (scan) { + /* Одна строка — аппаратный скролл окна + подрисовка одного ряда + * (как в MD/RAW), без перерисовки всего экрана. */ + case KEY_DOWN: + if (hex_top < mt) { + hex_top += HEX_BPR; + scroll(0, VIEW_TOP_ROW, SCREEN_W, VIEW_H, 1, 0); /* содержимое вверх */ + hex_draw_row(hex_top + HEX_SPAN, (uint8_t)(VIEW_TOP_ROW + VIEW_H - 1)); + } + break; + case KEY_UP: + if (hex_top) { + hex_top -= HEX_BPR; + scroll(0, VIEW_TOP_ROW, SCREEN_W, VIEW_H, 2, 0); /* содержимое вниз */ + hex_draw_row(hex_top, VIEW_TOP_ROW); + } + break; + case KEY_PGDN: { + uint32_t nt = hex_top + (uint32_t)VIEW_H * HEX_BPR; + if (nt > mt) nt = mt; + if (nt != hex_top) { hex_top = nt; hex_draw(); } + break; + } + case KEY_PGUP: { + uint32_t d = (uint32_t)VIEW_H * HEX_BPR; + uint32_t nt = (hex_top >= d) ? hex_top - d : 0; + if (nt != hex_top) { hex_top = nt; hex_draw(); } + break; + } + case KEY_HOME: + if (hex_top) { hex_top = 0; hex_draw(); } + break; + case KEY_END: + if (hex_top != mt) { hex_top = mt; hex_draw(); } + break; + default: + return 0; /* не наша клавиша */ + } + render_percent_progress(calc_hex_pct()); + return 1; +} + +#endif /* WITH_HEX */ diff --git a/examples/mdview2/mdview2_status.c b/examples/mdview2/mdview2_status.c index 04c40ad..6a0c32f 100644 --- a/examples/mdview2/mdview2_status.c +++ b/examples/mdview2/mdview2_status.c @@ -145,6 +145,16 @@ void render_raw_status(void) } #endif /* WITH_RAW */ +#if WITH_HEX +/* HEX-вариант числовой части бара (peer к render_raw_status). */ +void render_hex_status(void) +{ + textattr(ATTR_BAR); + gotoxy(DIV1_X + 1, 0); + bios_writeattr_until(" HEX", DIV2_X - DIV1_X - 1, ATTR_BAR, 0); +} +#endif /* WITH_HEX */ + /* ---- Нижнее меню (строка 31) -------------------------------------- */ void render_menu(void) @@ -168,9 +178,13 @@ void render_menu(void) #if WITH_RAW if (g_ready) /* RAW доступен после постройки документа */ put_str_attr(1 * 8 + 2, MENU_ROW, (g_view == VIEW_MD) ? "RAW" : "MD", ATTR_MENU_T); - if (g_view != VIEW_MD) /* Wrap/Unwrap — только в RAW */ + if (VIEW_IS_RAW(g_view)) /* Wrap/Unwrap — только в RAW */ put_str_attr(2 * 8 + 2, MENU_ROW, (g_view == VIEW_RAW_WRAP) ? "UnWrap" : "Wrap", ATTR_MENU_T); +#endif +#if WITH_HEX + if (g_ready) /* HEX доступен после постройки документа */ + put_str_attr(3 * 8 + 2, MENU_ROW, (g_view == VIEW_HEX) ? "Back" : "Hex", ATTR_MENU_T); #endif if (g_f8_enabled) /* смена кодировки сейчас возможна */ put_str_attr(7 * 8 + 2, MENU_ROW, "CodePg", ATTR_MENU_T);