mdview2: единая позиция при переключениях F2 (MD↔RAW) и F8 (8bit↔UTF-8)
Валюта позиции — байт-offset активного буфера: - line_at_off(off): обратный перевод offset → MD-строка (бинарный поиск по seg_off, оффсеты сегментов монотонны); - map_off(off, from, to): пропорциональный перенос позиции между буферами разного размера — один цикл restoring-деления, без __mullong/__divulong, точность from/65536; - raw_pos()/raw_reanchor(off) в RAW-модуле; raw_seed_from через reanchor, raw_home стал приватным (только клавиша Home). F2 RAW→MD: top_line = line_at_off(raw_pos()) — точное позиционирование. F8 между готовыми наборами: view_pos → map_off → view_reanchor вместо восстановления сохранённой позиции набора. Ленивая сборка — по-прежнему с начала (в RAW с raw_reanchor(0) и откатом при неудаче). Попутно: F8 в RAW-режиме больше не рисует MD-вид поверх RAW — перерисовка по g_view. exe 25100 → 25725 (+625). Проверено в MAME. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -826,6 +826,43 @@ static int build_doc(uint8_t slot, uint8_t enc, uint8_t visible)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Пропорциональный перенос байт-позиции между буферами разного размера
|
||||
* (8bit ↔ UTF-8 при F8): off * to / from БЕЗ __mullong/__divulong. Один
|
||||
* цикл restoring-деления: бит k дроби off/from (сравнение с from/2^k)
|
||||
* сразу добавляет to/2^k в результат — сумма to/2^k по установленным
|
||||
* битам и есть off*to/from. Точность from/65536 (≤4 байта на максимальном
|
||||
* файле); ляжет на границу строки через line_at_off / raw_reanchor. */
|
||||
static uint32_t map_off(uint32_t off, uint32_t from, uint32_t to)
|
||||
{
|
||||
if (from == to || from == 0) return off;
|
||||
uint32_t res = 0;
|
||||
for (uint8_t i = 0; i < 16; i++) {
|
||||
from >>= 1;
|
||||
to >>= 1;
|
||||
if (off >= from) { off -= from; res += to; }
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/* Байт-позиция текущего вида (верх экрана) — единая «валюта» для переноса
|
||||
* позиции между видами/наборами. */
|
||||
static uint32_t view_pos(void)
|
||||
{
|
||||
#if WITH_RAW
|
||||
if (g_view != VIEW_MD) return raw_pos();
|
||||
#endif
|
||||
return seg_off(top_line);
|
||||
}
|
||||
|
||||
/* Поставить текущий вид на байт-позицию off (после doc_switch). */
|
||||
static void view_reanchor(uint32_t off)
|
||||
{
|
||||
#if WITH_RAW
|
||||
if (g_view != VIEW_MD) { raw_reanchor(off); return; }
|
||||
#endif
|
||||
top_line = line_at_off(off);
|
||||
}
|
||||
|
||||
/* Переключает кодировку на `next` (вызывается из главного цикла по F8).
|
||||
* 8-бит↔8-бит внутри одного набора — мгновенный ремап; переход в другой набор
|
||||
* — мгновенный doc_switch, если он построен, иначе ЛЕНИВАЯ сборка по месту
|
||||
@@ -842,14 +879,23 @@ static void switch_encoding(uint8_t next)
|
||||
set_encoding(next);
|
||||
g_doc[target].enc = next;
|
||||
} else if (g_doc[target].built) { /* набор готов — мгновенный свап */
|
||||
doc_switch(target);
|
||||
/* Позицию переносим пропорцией байтов (буферы наборов разного
|
||||
* размера), а не из сохранённой в g_doc копии — иначе каждый набор
|
||||
* скачет по своей старой позиции. */
|
||||
uint32_t old_off = view_pos();
|
||||
uint32_t old_size = file_size;
|
||||
doc_switch(target);
|
||||
g_disp_doc = target;
|
||||
set_encoding(next);
|
||||
set_encoding(next);
|
||||
g_doc[target].enc = next;
|
||||
view_reanchor(map_off(old_off, old_size, file_size));
|
||||
} else { /* строим набор лениво */
|
||||
doc_save_live(g_active_doc); /* сохранить текущий (позиция и т.п.) */
|
||||
#if WITH_RAW
|
||||
g_ready = 0;
|
||||
uint32_t raw_save = raw_pos();
|
||||
if (g_view != VIEW_MD)
|
||||
raw_reanchor(0); /* прогрессивный показ нового буфера — с начала */
|
||||
g_ready = 0;
|
||||
render_menu(); /* идёт индексация — прячем F2 */
|
||||
#endif
|
||||
spinner_show(1);
|
||||
@@ -861,9 +907,13 @@ static void switch_encoding(uint8_t next)
|
||||
render_menu();
|
||||
#endif
|
||||
if (rc < 0) { /* нет EMM — откат на текущий набор */
|
||||
if (target == DOC_UTF8)
|
||||
if (target == DOC_UTF8)
|
||||
g_utf_failed = 1;
|
||||
doc_load_live(g_active_doc);
|
||||
#if WITH_RAW
|
||||
if (g_view != VIEW_MD)
|
||||
raw_reanchor(raw_save); /* буфер прежний — вернуть позицию RAW */
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
g_disp_doc = target; /* build_doc уже выставил active/enc */
|
||||
@@ -1036,6 +1086,7 @@ int main(int argc, char **argv)
|
||||
} else {
|
||||
g_raw_last = g_view; /* запомнить под-режим RAW */
|
||||
g_view = VIEW_MD;
|
||||
top_line = line_at_off(raw_pos()); /* позиция из RAW */
|
||||
clamp_top();
|
||||
render_full_status(); render_menu();
|
||||
draw_viewport_from_cache();
|
||||
@@ -1050,9 +1101,18 @@ int main(int argc, char **argv)
|
||||
if (next == ENC_UTF8 && g_utf_failed)
|
||||
next = ENC_CP866; /* UTF-8 недоступен */
|
||||
switch_encoding(next);
|
||||
if (g_abort)
|
||||
if (g_abort)
|
||||
exit(0); /* Esc/F10 во время ленивой досборки */
|
||||
render_full_status(); /* перерисовка — в MD-режиме */
|
||||
/* Перерисовка — по текущему виду (switch_encoding сам не рисует). */
|
||||
#if WITH_RAW
|
||||
if (g_view != VIEW_MD) {
|
||||
status_encoding();
|
||||
render_raw_status();
|
||||
raw_draw();
|
||||
continue;
|
||||
}
|
||||
#endif
|
||||
render_full_status();
|
||||
draw_viewport_from_cache();
|
||||
continue;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user