Горизонтальный скролл (Фаза 5, финал):
- Скроллим по ТИПУ, а не по длине: новый флаг IF_HSCROLL ставится только
на код и таблицы; HR и границы fence (IF_NOWRAP без IF_HSCROLL) не
двигаются. Блок едет целиком, включая строки короче 80.
- Обход бага кодогенерации SDCC z80: `if (n!=g) g=n;` пишет (n-g) вместо n
(SUB сравнения затирает A, store переиспользует испорченный A). Лечится
записью viewport_x ДО сравнения. Минимальный репродьюсер и оба описания
для трекера — в docs/bugs/sdcc-z80-cmp-store-a/ (воспроизводится на чистом
sdcc 4.5, в т.ч. с --no-peep → это кодогенератор, не peephole).
Рендеринг:
- Отступленный fence (```c внутри списка) теперь распознаётся: is_fence_raw
пропускает ведущие пробелы/табы; то же в рендере прячет строку-границу.
- Строки-разделители (HR, ровно 80) больше не участвуют в скролле.
Чистка: удалён мёртвый код (is_fence_delim, get_init_style[_raw], is_cont,
seg_flags). Makefile (mdview/mdview2): iconv UTF-8→CP866 завершается ненулевым
кодом при отбрасывании символов — игнорируем (|| true).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
New examples/mdview2 — render-cache version of mdview: each logical
line is rendered into an EMM (char,attr) buffer once during file load
(interleaved with index_lines()), then scrolling draws straight from
the cache via ESTEX WINREST, with no re-parsing or fb() access in the
steady state. Horizontal scroll still uses the old live-render path
(Phase 5, not yet migrated).
Format and budget were derisked empirically first (tests/winrest):
confirmed ESTEX WINCOPY/WINREST buffer layout and measured EMM free
space, both folded into the implementation.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>