c0dd1621e6
Вынос подсистем из mdview2.c в отдельные C-модули для читаемости и навигации. mdview2.c: 2740 → 1062 строк (-61%); ядро теперь чистая инфраструктура (cache-пул, EMM/fb, загрузка файла, doc-slot, loading-loop, build_doc, main). Модули (через EXTRA_SRCS, общий интерфейс в mdview2.h): - mdview2_help.c — диалог справки F1 - mdview2_table.c — выровненная отрисовка таблиц - mdview2_enc.c — кодировки CP866/CP1251/KOI8R + UTF-8 конвертер - mdview2_view.c — отрисовка области/статус-бара/меню + прокрутка - mdview2_index.c — парсер/индексатор markdown (сердце приложения) (mdview2_raw.c был выделен ранее) Чистый перенос static→extern; приватное состояние подсистем осталось приватным. Размер: exe 28090 → 28112 (+22 Б / +0.08% — codegen-шум на двух сильно связанных модулях enc/index). Сборка чистая, smoke-тест ОК. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
92 lines
3.5 KiB
C
92 lines
3.5 KiB
C
/*
|
||
* mdview2_table.c — выровненная отрисовка markdown-таблиц.
|
||
*
|
||
* Разбор |-разделённых ячеек и эмиссия рамок/строк в общий буфер ячеек
|
||
* рендера (gc_put/gc_fill, см. mdview2.h). Вызывается из index_lines()
|
||
* ядра при обнаружении таблицы. Геометрия рамок (TBL_n), словарь стилей
|
||
* (CK_n, INIT_STYLE_n) и cell-buffer API объявлены в mdview2.h.
|
||
*/
|
||
|
||
#include <stdint.h>
|
||
#include <conio.h> /* COLOR() / COLOR_* для атрибутов TBL_ATTR/ATTR_TEXT */
|
||
#include "mdview2.h"
|
||
|
||
uint32_t row_end(uint32_t p)
|
||
{
|
||
while (p < file_size && fb(p) != '\n') p++;
|
||
return p;
|
||
}
|
||
|
||
/* Начало контента первой ячейки строки (после ведущих пробелов и '|'). */
|
||
uint32_t table_first_cell(uint32_t row_start)
|
||
{
|
||
uint32_t p = row_start;
|
||
while (p < file_size && fb(p) == ' ') p++;
|
||
if (p < file_size && fb(p) == '|') p++;
|
||
return p;
|
||
}
|
||
|
||
/* Следующая ячейка: [*cs,*ce) — обрезанный диапазон; *pp продвигается за '|'.
|
||
* 0 — ячеек больше нет (включая хвостовую пустоту после последнего '|'). */
|
||
uint8_t table_next_cell(uint32_t *pp, uint32_t lineend, uint32_t *cs, uint32_t *ce)
|
||
{
|
||
uint32_t p = *pp;
|
||
if (p >= lineend) return 0;
|
||
uint32_t a = p;
|
||
while (p < lineend && fb(p) != '|') p++;
|
||
uint32_t b = p;
|
||
uint8_t had_pipe = (uint8_t)(p < lineend && fb(p) == '|');
|
||
if (had_pipe) p++;
|
||
*pp = p;
|
||
while (a < b && fb(a) == ' ') a++;
|
||
while (b > a && fb(b - 1) == ' ') b--;
|
||
if (!had_pipe && a == b) return 0;
|
||
*cs = a; *ce = b;
|
||
return 1;
|
||
}
|
||
|
||
/* Строка-разделитель (|---|:-:|): каждая ячейка непустая и только '-'/':'. */
|
||
uint8_t table_is_sep_row(uint32_t row_start, uint32_t lineend)
|
||
{
|
||
uint32_t p = table_first_cell(row_start);
|
||
uint32_t cs, ce;
|
||
uint8_t n = 0;
|
||
while (table_next_cell(&p, lineend, &cs, &ce)) {
|
||
if (cs >= ce) return 0;
|
||
for (uint32_t q = cs; q < ce; q++) { char c = fb(q); if (c != '-' && c != ':') return 0; }
|
||
n++;
|
||
}
|
||
return (uint8_t)(n > 0);
|
||
}
|
||
|
||
/* Горизонтальная рамка в g_cells: left + (H×(w+2) + mid|right) по колонкам. */
|
||
void table_border(const uint8_t *widths, uint8_t ncols, char left, char mid, char right)
|
||
{
|
||
gc_put(left, TBL_ATTR);
|
||
for (uint8_t c = 0; c < ncols; c++) {
|
||
gc_fill(TBL_H, TBL_ATTR, (uint8_t)(widths[c] + 2));
|
||
gc_put((c == (uint8_t)(ncols - 1)) ? right : mid, TBL_ATTR);
|
||
}
|
||
}
|
||
|
||
/* Строка данных в g_cells: │ <ячейка, добитая до widths[c]> │ … */
|
||
void table_data_row(uint32_t row_start, uint32_t lineend, const uint8_t *widths, uint8_t ncols)
|
||
{
|
||
uint32_t p = table_first_cell(row_start);
|
||
uint32_t cs, ce;
|
||
gc_put(TBL_V, TBL_ATTR);
|
||
for (uint8_t c = 0; c < ncols; c++) {
|
||
uint8_t got = table_next_cell(&p, lineend, &cs, &ce);
|
||
gc_put(' ', TBL_ATTR);
|
||
uint8_t rendered = 0;
|
||
if (got && ce > cs) {
|
||
uint8_t before = g_ncells;
|
||
(void)inline_scan(cs, ce, 0, CK_OTHER, INIT_STYLE_PLAIN, ATTR_TEXT, 1);
|
||
rendered = (uint8_t)(g_ncells - before);
|
||
}
|
||
if (rendered < widths[c]) gc_fill(' ', ATTR_TEXT, (uint8_t)(widths[c] - rendered));
|
||
gc_put(' ', TBL_ATTR);
|
||
gc_put(TBL_V, TBL_ATTR);
|
||
}
|
||
}
|