mdview2: статус-бар в отдельный модуль, упростить alloc_set_storage
- mdview2_status.c: вынести статус-бар/меню/спиннер из ядра - mdview2.c: убрать retry-цикл в alloc_set_storage (fail-fast вместо ложной устойчивости — при нехватке EMM под индекс контент тоже не влезет) - mdview2.h: дополнить экспортами статус-модуля - mdview2_md.c / mdview2_raw.c: зачистка после расщепления - mdview/mdview.c: переименовать scroll_* → md_scroll_* (симметрия) - docs/fast_ram.md, docs/turboc.txt: добавить справочные доки - examples/mdview2/README.MD, READMEBG.MD: обновить описание Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+48
-114
@@ -1,6 +1,7 @@
|
||||
/*
|
||||
* mdview2_md.c — представление MD-документа (peer к mdview2_raw.c): отрисовка
|
||||
* области из рендер-кэша, статус-бар, нижнее меню и прокрутка (верт./гориз.).
|
||||
* области из рендер-кэша + прокрутка (верт./гориз.) + навигация md_key().
|
||||
* Статус-бар, меню и спиннер — в mdview2_status.c (общие для MD/RAW).
|
||||
*
|
||||
* Работает поверх готового рендер-кэша (cache_dir_get → cache_rec_t) и
|
||||
* состояния навигации (top_line/viewport_x/n_lines, см. mdview2.h). Никакого
|
||||
@@ -11,8 +12,7 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h> /* dec8/dec16 */
|
||||
#include <conio.h> /* wrchar/gotoxy/cputs/textattr/scroll/COLOR */
|
||||
#include <conio.h> /* wrchar/scroll/COLOR */
|
||||
#include <bios/text.h> /* bios_set_place/bios_fillcharattr */
|
||||
#include "mdview2.h"
|
||||
|
||||
@@ -61,101 +61,6 @@ void draw_viewport_from_cache(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* Число строк, готовых к показу. Во время загрузки последняя эмитированная
|
||||
* строка ещё в g_cells (не зафлашена), поэтому доступны [0..n_lines-2]. */
|
||||
uint16_t drawable_lines(void)
|
||||
{
|
||||
if (g_loading) return (n_lines >= 1) ? (uint16_t)(n_lines - 1) : 0;
|
||||
return n_lines;
|
||||
}
|
||||
|
||||
/* Возвращает процент прокрутки (0..100) относительно доступного диапазона. */
|
||||
static uint8_t calc_pct(void)
|
||||
{
|
||||
uint16_t total = drawable_lines();
|
||||
uint8_t pct;
|
||||
if (total <= VIEW_H)
|
||||
pct = 100;
|
||||
else
|
||||
pct = (uint8_t)((uint32_t)top_line * 100UL / (uint32_t)(total - VIEW_H));
|
||||
return pct;
|
||||
}
|
||||
|
||||
/* Рисует динамическую часть статус-бара без printf.
|
||||
* Полностью перезаписывает колонки 45..79, чтобы не оставлять «хвосты». */
|
||||
void render_status_numbers(void)
|
||||
{
|
||||
uint16_t total = drawable_lines();
|
||||
uint16_t last = top_line + VIEW_H;
|
||||
if (last > total) last = total;
|
||||
uint8_t pct = calc_pct();
|
||||
|
||||
textattr(ATTR_BAR);
|
||||
bios_set_place(0, 45);
|
||||
bios_fillcharattr(' ', ATTR_BAR, (uint8_t)(SCREEN_W - 45));
|
||||
|
||||
wrchar(45, 0, 0xB3, ATTR_BAR); /* вертикальный разделитель */
|
||||
gotoxy(47, 0);
|
||||
cputs("L ");
|
||||
dec16(top_line + 1);
|
||||
cputs("-");
|
||||
dec16(last);
|
||||
cputs(" / ");
|
||||
dec16(total);
|
||||
if (g_loading) cputs("..."); /* ещё грузится */
|
||||
|
||||
wrchar(70, 0, 0xB3, ATTR_BAR); /* вертикальный разделитель */
|
||||
gotoxy( 73, 0);
|
||||
dec8(pct);
|
||||
cputs("%");
|
||||
}
|
||||
|
||||
/* Полностью перерисовывает статус-бар (заголовок + числа). */
|
||||
void render_full_status(void)
|
||||
{
|
||||
|
||||
fill_row(0, ATTR_BAR);
|
||||
/* Размещение в шапке: "MDVIEW", затем слот спиннера и имя файла. */
|
||||
put_str_attr(1, 0, "MDVIEW", ATTR_BAR);
|
||||
put_str_attr(10, 0, filename, ATTR_BAR);
|
||||
put_str_attr(37, 0, enc_name(g_encoding), ATTR_BAR); /* текущая кодировка */
|
||||
render_status_numbers();
|
||||
}
|
||||
|
||||
/* Обновляет только изменяемую числовую часть статус-бара. */
|
||||
void render_updated_status(void)
|
||||
{
|
||||
render_status_numbers();
|
||||
}
|
||||
|
||||
/* Отрисовывает нижнюю строку меню. */
|
||||
void render_menu(void)
|
||||
{
|
||||
/* Блок i = колонка i*8 (8 шириной): 2 поз. НОМЕР клавиши без 'F' (стиль
|
||||
* ATTR_MENU_K, ведущий «чёрный» пробел кроме F10) + 6 поз. ТЕКСТ-функция
|
||||
* (ATTR_MENU_T) сразу за номером. Номера рисуем для ВСЕХ 10 клавиш; текст —
|
||||
* только у задействованных и доступных сейчас. */
|
||||
fill_row(MENU_ROW, ATTR_MENU_T);
|
||||
|
||||
char num[3]; num[2] = 0;
|
||||
for (uint8_t i = 0; i < 9; i++) { /* F1..F9: ' 1'..' 9' */
|
||||
num[0] = ' '; num[1] = (char)('1' + i);
|
||||
put_str_attr((uint8_t)(i * 8), MENU_ROW, num, ATTR_MENU_K);
|
||||
}
|
||||
put_str_attr(9 * 8, MENU_ROW, "10", ATTR_MENU_K); /* F10 */
|
||||
|
||||
put_str_attr(0 * 8 + 2, MENU_ROW, "Help", ATTR_MENU_T);
|
||||
#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 */
|
||||
put_str_attr(2 * 8 + 2, MENU_ROW,
|
||||
(g_view == VIEW_RAW_WRAP) ? "UnWrap" : "Wrap", ATTR_MENU_T);
|
||||
#endif
|
||||
if (g_f8_enabled) /* смена кодировки сейчас возможна */
|
||||
put_str_attr(7 * 8 + 2, MENU_ROW, "CodePg", ATTR_MENU_T);
|
||||
put_str_attr(9 * 8 + 2, MENU_ROW, "Exit", ATTR_MENU_T);
|
||||
}
|
||||
|
||||
/* ==================================================================
|
||||
* Прокрутка
|
||||
@@ -172,7 +77,7 @@ void clamp_top(void)
|
||||
}
|
||||
|
||||
/* Прокрутка вверх на n строк с частичной перерисовкой при n == 1. */
|
||||
void scroll_up(uint16_t n)
|
||||
void md_scroll_up(uint16_t n)
|
||||
{
|
||||
uint16_t new_top_line = (top_line >= n) ? (uint16_t)(top_line - n) : 0;
|
||||
if( new_top_line != top_line) {
|
||||
@@ -187,7 +92,7 @@ void scroll_up(uint16_t n)
|
||||
}
|
||||
|
||||
/* Прокрутка вниз на n строк с частичной перерисовкой при n == 1. */
|
||||
void scroll_down(uint16_t n)
|
||||
void md_scroll_down(uint16_t n)
|
||||
{
|
||||
uint16_t new_top_line = (top_line + n < n_lines - VIEW_H) ?
|
||||
(uint16_t)(top_line + n) : n_lines - VIEW_H;
|
||||
@@ -208,7 +113,7 @@ void scroll_down(uint16_t n)
|
||||
* Фаза 5: ширина берётся прямо из директории кэша (rec.len — уже
|
||||
* посчитанная реальная длина в ячейках после рендера), без единого
|
||||
* обращения к fb()/seg_off()/исходному файлу. */
|
||||
void scroll_h(int8_t delta)
|
||||
void md_scroll_horizon(int8_t delta)
|
||||
{
|
||||
uint16_t maxw = 0;
|
||||
for (uint8_t i = 0; i < VIEW_H; i++) {
|
||||
@@ -247,6 +152,14 @@ void scroll_h(int8_t delta)
|
||||
draw_viewport_from_cache();
|
||||
}
|
||||
|
||||
/* Процент прокрутки (0..100) относительно доступного диапазона. */
|
||||
static uint8_t calc_md_pct(void)
|
||||
{
|
||||
uint16_t total = drawable_lines();
|
||||
if (total <= VIEW_H) return 100;
|
||||
return (uint8_t)((uint32_t)top_line * 100UL / (uint32_t)(total - VIEW_H));
|
||||
}
|
||||
|
||||
/* ---- навигация MD после загрузки (peer к raw_key) ---------------- */
|
||||
|
||||
/* Обрабатывает навигационную клавишу в MD-режиме (вызывается из главного
|
||||
@@ -255,19 +168,40 @@ void scroll_h(int8_t delta)
|
||||
uint8_t md_key(uint8_t scan)
|
||||
{
|
||||
switch (scan) {
|
||||
case KEY_UP: scroll_up(1); break;
|
||||
case KEY_DOWN: scroll_down(1); break;
|
||||
case KEY_LEFT: scroll_h(-(int8_t)HPAN_STEP); break;
|
||||
case KEY_RIGHT: scroll_h(+(int8_t)HPAN_STEP); break;
|
||||
case KEY_PGUP: scroll_up(VIEW_H); break;
|
||||
case KEY_PGDN: scroll_down(VIEW_H); break;
|
||||
case KEY_HOME: top_line = 0; viewport_x = 0;
|
||||
draw_viewport_from_cache(); break;
|
||||
case KEY_END: top_line = (n_lines > VIEW_H) ? (uint16_t)(n_lines - VIEW_H) : 0;
|
||||
viewport_x = 0;
|
||||
draw_viewport_from_cache(); break;
|
||||
default: return 0; /* не наша клавиша */
|
||||
case KEY_UP:
|
||||
md_scroll_up(1);
|
||||
break;
|
||||
case KEY_DOWN:
|
||||
md_scroll_down(1);
|
||||
break;
|
||||
case KEY_LEFT:
|
||||
md_scroll_horizon(-(int8_t)HPAN_STEP);
|
||||
break;
|
||||
case KEY_RIGHT:
|
||||
md_scroll_horizon(+(int8_t)HPAN_STEP);
|
||||
break;
|
||||
case KEY_PGUP:
|
||||
md_scroll_up(VIEW_H);
|
||||
break;
|
||||
case KEY_PGDN:
|
||||
md_scroll_down(VIEW_H);
|
||||
break;
|
||||
case KEY_HOME:
|
||||
top_line = 0;
|
||||
viewport_x = 0;
|
||||
draw_viewport_from_cache();
|
||||
break;
|
||||
case KEY_END:
|
||||
top_line = (n_lines > VIEW_H) ? (uint16_t)(n_lines - VIEW_H) : 0;
|
||||
viewport_x = 0;
|
||||
draw_viewport_from_cache();
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0; /* не наша клавиша */
|
||||
}
|
||||
render_updated_status();
|
||||
|
||||
render_percent_progress(calc_md_pct());
|
||||
render_md_status_numbers();
|
||||
return 1;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user