mdview2: фоновая сборка второго набора кодировки в паузах между клавишами; версия v1.0 (b3)
- индексатор порезан на резюмируемые шаги index_begin/index_step/index_finish; межшаговое состояние в статиках модуля, в docset_t не входит - bg_build_start/bg_step: второй набор (UTF-8 при 8-битном первичном и наоборот) строится в idle главного цикла; холдаун после клавиш, спиннер погашен (g_bg_building) — фон незаметен - F8 до готовности докручивает начатое фоном (ветка resume в build_doc), а не строит заново; общий setup вынесен в doc_setup - кодировка в статус-баре показывается сразу (детект/F8), не дожидаясь конца индексации - побочный фикс: UTF-конвертация впереди проверки останова — >4КБ абзац больше не обрывает конвертацию остатка - README.md (новый, v1.0 b3), CHANGELOG.md; дискета: README/DEMO/CHANGES в трёх кодировках (пути автодетекта) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
+125
-16
@@ -203,10 +203,12 @@ static uint8_t g_raw_last = VIEW_RAW_WRAP; /* последний под
|
||||
static uint8_t g_hex_last = VIEW_MD; /* вид, из которого вошли в HEX (возврат по F4) */
|
||||
#endif
|
||||
#endif
|
||||
uint8_t g_loading; /* extern: 1 во время index_lines() */
|
||||
uint8_t g_loading; /* extern: 1 во время видимой индексации (build_doc) */
|
||||
static uint8_t g_first_drawn; /* первый экран уже нарисован */
|
||||
uint8_t g_f8_enabled; /* extern: можно ли сейчас переключать кодировку */
|
||||
static uint8_t g_utf_failed; /* UTF-8 набор не удалось построить (нет EMM) — пропускаем UTF-8 в цикле F8 */
|
||||
uint8_t g_bg_building; /* extern: 1 во время фонового index_step — гасит спиннер индексатора */
|
||||
static uint8_t g_bg_doc = 0xFF; /* слот, строящийся в фоне (bg_step); 0xFF = фоновой сборки нет */
|
||||
uint8_t g_abort; /* extern: F10/Esc во время загрузки → прервать индексацию */
|
||||
static uint16_t g_last_prog; /* n_lines на последнем обновлении статуса */
|
||||
|
||||
@@ -768,26 +770,34 @@ void progress_tick(void)
|
||||
* Точка входа
|
||||
* ================================================================== */
|
||||
|
||||
/* Строит набор `slot` кооперативно (index_lines + progress_tick).
|
||||
/* Строит набор `slot` кооперативно (index_step + progress_tick).
|
||||
* visible=1 — первичный (показываемый): прогрессивная отрисовка первого экрана
|
||||
* и скролл по готовым строкам. visible=0 — вторичный: index_lines строит его в
|
||||
* живых глобалах, а progress_tick через свап показывает/листает уже готовый
|
||||
* и скролл по готовым строкам. visible=0 — вторичный: индексация идёт в живых
|
||||
* глобалах, а progress_tick через свап показывает/листает уже готовый
|
||||
* g_disp_doc. Возврат: 0 — успех, <0 — нехватка EMM (-5/-6/-7).
|
||||
*
|
||||
* Если slot прямо сейчас строится ФОНОМ (g_bg_doc, см. bg_step ниже) —
|
||||
* не начинаем заново, а ДОКРУЧИВАЕМ: загружаем частично построенный набор
|
||||
* и продолжаем с сохранённой позиции индексатора (его межшаговое состояние
|
||||
* живёт в статиках модуля index и переживает свапы наборов).
|
||||
*
|
||||
* UTF-8 набор конвертируется ИНКРЕМЕНТАЛЬНО: выделяем страницы, переключаем
|
||||
* живой буфер на utf и запускаем конвертацию первого чанка; дальше index_lines
|
||||
* живой буфер на utf и запускаем конвертацию первого чанка; дальше index_step
|
||||
* докручивает её впереди позиции чтения (g_utf_building). Конвертер читает
|
||||
* оригинал из orig_file_phys[] через cv_read (не через fb, который теперь
|
||||
* указывает на utf). */
|
||||
static int build_doc(uint8_t slot, uint8_t enc, uint8_t visible)
|
||||
/* Настраивает живые глобалы под сборку набора slot: файловый буфер (utf/orig),
|
||||
* индекс + директория кэша, сброс индексатора. Общая часть build_doc и
|
||||
* bg_build_start. Возврат: 0 — успех, <0 — нехватка EMM (-5/-6/-7). */
|
||||
static int doc_setup(uint8_t slot)
|
||||
{
|
||||
if (slot == DOC_UTF8) {
|
||||
if (!utf_avail) { /* первый вход: выделить страницы */
|
||||
if (!utf_alloc())
|
||||
if (!utf_alloc())
|
||||
return -7; /* выделяет страницы + сбрасывает конвертер */
|
||||
utf_avail = 1;
|
||||
}
|
||||
file_blk = utf_blk;
|
||||
file_blk = utf_blk;
|
||||
file_pages = utf_pages;
|
||||
memcpy(file_phys, utf_phys, MAX_PAGES);
|
||||
if (g_utf_building) {
|
||||
@@ -798,29 +808,45 @@ static int build_doc(uint8_t slot, uint8_t enc, uint8_t visible)
|
||||
file_size = utf_size;
|
||||
}
|
||||
} else {
|
||||
file_blk = orig_file_blk;
|
||||
file_pages = orig_file_pages;
|
||||
file_blk = orig_file_blk;
|
||||
file_pages = orig_file_pages;
|
||||
file_size = orig_file_size;
|
||||
memcpy(file_phys, orig_file_phys, MAX_PAGES);
|
||||
}
|
||||
cur_page = 0xFF;
|
||||
|
||||
int rc = alloc_set_storage();
|
||||
if (rc < 0)
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
index_begin();
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int build_doc(uint8_t slot, uint8_t enc, uint8_t visible)
|
||||
{
|
||||
if (g_bg_doc == slot) { /* фон уже строит его — продолжить */
|
||||
doc_load_live(slot);
|
||||
g_bg_doc = 0xFF;
|
||||
} else {
|
||||
int rc = doc_setup(slot);
|
||||
if (rc < 0)
|
||||
return rc;
|
||||
}
|
||||
|
||||
set_encoding(enc);
|
||||
top_line = 0;
|
||||
top_line = 0;
|
||||
viewport_x = 0;
|
||||
g_active_doc = slot;
|
||||
if (visible) {
|
||||
g_disp_doc = slot;
|
||||
g_first_drawn = 0;
|
||||
if (visible) {
|
||||
g_disp_doc = slot;
|
||||
g_first_drawn = 0;
|
||||
status_encoding(); /* показать кодировку сразу (детект/F8), не дожидаясь индексации */
|
||||
cur_page = 0xFF; /* BIOS-вывод мог сбить W3-маппинг, на который опирается fb() */
|
||||
}
|
||||
|
||||
g_loading = 1;
|
||||
g_last_prog = 0;
|
||||
index_lines();
|
||||
while (!index_step(255)) {}
|
||||
g_loading = 0;
|
||||
|
||||
/* Зафиксировать конвертацию (на случай обрыва индекса по max_lines до конца
|
||||
@@ -835,6 +861,69 @@ static int build_doc(uint8_t slot, uint8_t enc, uint8_t visible)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ==================================================================
|
||||
* Фоновая сборка второго набора (idle-time, между клавишами)
|
||||
* ==================================================================
|
||||
* Пока пользователь читает документ, главный цикл в паузах между клавишами
|
||||
* докручивает индексацию второго набора (UTF-8 при 8-битном первичном и
|
||||
* наоборот) порциями index_step: свап на bg-набор → несколько итераций →
|
||||
* свап обратно. Экран при этом не трогается (g_bg_building гасит спиннер),
|
||||
* задержка реакции на клавишу — не больше одного шага. По готовности F8
|
||||
* переключает наборы мгновенно; F8 ДО готовности докручивает сборку видимо
|
||||
* (ветка resume в build_doc), не начиная её заново. */
|
||||
|
||||
#define BG_STEP_BUDGET 2u /* итераций индексатора на idle-шаг: латентность клавиши
|
||||
* = длительность шага (~единицы мс на обычном абзаце) */
|
||||
#define BG_KEY_HOLDOFF 300u /* пустых опросов kbhit после клавиши до возобновления
|
||||
* фона — при автоповторе (скролл) фон не вклинивается */
|
||||
|
||||
/* Готовит фоновую сборку второго набора: настраивает живые глобалы (буфер,
|
||||
* индекс, кэш, index_begin) так же, как build_doc, но БЕЗ индексации, и
|
||||
* возвращает живым прежний набор. При нехватке EMM фон просто не стартует —
|
||||
* остаётся сегодняшний ленивый путь по F8. */
|
||||
static void bg_build_start(void)
|
||||
{
|
||||
uint8_t slot = (uint8_t)((g_active_doc == DOC_8BIT) ? DOC_UTF8 : DOC_8BIT);
|
||||
uint8_t vis = g_active_doc;
|
||||
if (g_doc[slot].built || (slot == DOC_UTF8 && g_utf_failed))
|
||||
return; /* строить нечего */
|
||||
|
||||
doc_save_live(vis);
|
||||
if (doc_setup(slot) < 0) { /* нет EMM — как и в ленивом пути */
|
||||
if (slot == DOC_UTF8) g_utf_failed = 1;
|
||||
doc_load_live(vis);
|
||||
return;
|
||||
}
|
||||
top_line = 0;
|
||||
viewport_x = 0;
|
||||
|
||||
g_active_doc = slot; /* живые глобалы = bg-набор... */
|
||||
doc_switch(vis); /* ...сохранить его и вернуть видимый */
|
||||
g_bg_doc = slot;
|
||||
}
|
||||
|
||||
/* Один idle-шаг фона: свап на строящийся набор, порция индексации, свап
|
||||
* обратно. Межшаговое состояние индексатора/UTF-конвертера — статики их
|
||||
* модулей, обработчики клавиш видимого набора их не трогают. По завершении
|
||||
* финализирует набор (дальше F8 переключается мгновенно). */
|
||||
static void bg_step(void)
|
||||
{
|
||||
uint8_t vis = g_active_doc;
|
||||
doc_switch(g_bg_doc);
|
||||
g_bg_building = 1;
|
||||
uint8_t done = index_step(BG_STEP_BUDGET);
|
||||
g_bg_building = 0;
|
||||
if (done) {
|
||||
if (g_utf_building) { /* как build_doc: обрыв индекса до конца исходника */
|
||||
utf_size = file_size;
|
||||
g_utf_building = 0;
|
||||
}
|
||||
g_doc[g_bg_doc].built = 1; /* doc_save_live поле built не трогает */
|
||||
g_bg_doc = 0xFF;
|
||||
}
|
||||
doc_switch(vis);
|
||||
}
|
||||
|
||||
/* Пропорциональный перенос байт-позиции между буферами разного размера
|
||||
* (8bit ↔ UTF-8 при F8): off * to / from БЕЗ __mullong/__divulong. Один
|
||||
* цикл restoring-деления: бит k дроби off/from (сравнение с from/2^k)
|
||||
@@ -1079,7 +1168,27 @@ int main(int argc, char **argv)
|
||||
render_full_status();
|
||||
draw_viewport_from_cache();
|
||||
|
||||
/* Второй набор (UTF-8 при 8-битном первичном и наоборот) готовим фоном
|
||||
* в паузах между клавишами — к первому F8 он обычно уже построен. */
|
||||
bg_build_start();
|
||||
|
||||
for (;;) {
|
||||
/* Idle-фон: пока второй набор не достроен, вместо блокирующего getkey
|
||||
* опрашиваем клавиатуру и тратим паузы на bg_step. Холдаун после
|
||||
* каждой клавиши: при активном скролле (автоповтор) фон молчит и
|
||||
* плавность не страдает. После достройки — снова блокирующий getkey. */
|
||||
if (g_bg_doc != 0xFF) {
|
||||
uint16_t idle = 0;
|
||||
while (!kbhit()) {
|
||||
if (idle < BG_KEY_HOLDOFF) {
|
||||
idle++;
|
||||
continue;
|
||||
}
|
||||
bg_step();
|
||||
if (g_bg_doc == 0xFF)
|
||||
break;
|
||||
}
|
||||
}
|
||||
uint16_t k = getkey();
|
||||
uint8_t ascii = (uint8_t)(k & 0xFF);
|
||||
uint8_t scan = (uint8_t)((k >> 8) & 0x7F);
|
||||
|
||||
Reference in New Issue
Block a user