mdview: speed up rendering via bios/text.h, fix wrap-boundary style bug
Replace per-character wrchar() loops in render_line/fill_row/help screens with batched BIOS calls (bios_writeattr/bios_fillcharattr), and cache the per-line index record (idx_get) instead of refetching it ~13 times per rendered line — each refetch cost two W3 bank switches via bank_read(). Also fixes a pre-existing indexer bug: when word-wrap pushes a token that starts with an emphasis/code marker (e.g. `_text_`) onto a new line, the marker got re-scanned a second time during the wrap continuation, flipping line_style back off and corrupting the rendered attribute of the next word. Fixed by snapshotting line_style at the last seen space and rolling back to that snapshot (both the saved continuation style and the live scan state) when a wrap is taken. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,180 @@
|
||||
Новое требование к первоначальной подготовке документа.
|
||||
|
||||
Правила форматирования и показа -
|
||||
1) Деление на параграфы. Параграфы разделяются пустыми строками.
|
||||
2) Заголовки H1-H6 - отдельные параграфы (после них всегда пустые строки)
|
||||
3) Разделители (---) - тоже - после них всегда пустые строки.
|
||||
4) Таблица/код (через ```)/списки - это единый параграф.
|
||||
|
||||
Типы текста (строк) -
|
||||
|
||||
Обычный текст
|
||||
|
||||
Может в оригинале находиться на нескольких строках.
|
||||
Строки могут разделяться
|
||||
- обычный break - это когда на строке после текста идет перевод строки -
|
||||
такой текст просто объединяется (в нашем случае если возможно то следующая строка продолжает
|
||||
выводиться на той же строке что и предыдущая, только отделяется от нее уже не переводом строки
|
||||
а через пробел.
|
||||
- широкий break - это когда перед переводом строки есть два или более пробелов или перед переводом
|
||||
строки находится символ обратный слэш '\' - в этом случае и когда мы выводим текст на экран следующая
|
||||
строка начинается с новой строки.
|
||||
- жесткий break - это когда две строки обычного текста разделяются двумя или более переводами
|
||||
стрки (то есть между ними как минимум есть одна пустая строка) - в этом случае вторая строка
|
||||
будет считаться новым параграфом и отделяться от предыдущей строки ОДНОЙ пустой строкой (вне
|
||||
зависимости от того сколько пустых строк в оригинале.
|
||||
Должно сохраняться действие модификатора bold/italic/strike начатое на одной строке на следующие
|
||||
если они так же находятся в этом параграфе. Новый параграф (после пустой строки) теряет воздействие
|
||||
незакрытого модификатора из предыдущего параграфа.
|
||||
Тип переноса строк - Wrap.
|
||||
|
||||
Заголовки -
|
||||
|
||||
абзацы из одной оригинальной строки. Начальный стиль зависит от типа заголовка (в нем могут встречаться
|
||||
модификаторы bold/italic/code/strike.
|
||||
Тип переноса строк - Wrap.
|
||||
|
||||
Разделитель (horizontal rules) -
|
||||
|
||||
Всегда одна строка. После нее выводим пустую строку всегда (следующий текст - новый абзац)
|
||||
|
||||
Списки
|
||||
|
||||
как и в обычном тексте - один пункт списка может находиться в оригинале на нескольких строках.
|
||||
если появляется новая строка с префиксом пункта списка - это означает что с этой строки начинается
|
||||
новый пункт списка. если появляется пустая строка - это означает что следующая за пустой строкой
|
||||
непустая строка уже не является продолжением пункта списка.
|
||||
Если следующая за пустой строкой строка так же является пунктом списка то такая строка считается
|
||||
продолжением текущего списка. Только если две строки списков разделены ДВУМЯ и более пустыми
|
||||
строками то вторая строка с пунктом списка будет считаться началом нового списка -
|
||||
Пример -
|
||||
|
||||
- строка 1
|
||||
- строка 2
|
||||
строка 3
|
||||
- строка 4
|
||||
|
||||
- строка 5
|
||||
|
||||
|
||||
- строка 6
|
||||
|
||||
Должно отображаться так -
|
||||
|
||||
- строка 1
|
||||
- строка 2 строка 3
|
||||
- строка 4
|
||||
- строка 5
|
||||
|
||||
- строка 6
|
||||
|
||||
Тип переноса строк - Wrap.
|
||||
Замечание - перенесенная строка продолжение пункта списка должна начинаться с отступа в
|
||||
несколько пробелов (для списка первого уровня - два пробела) - то есть с той же позиции
|
||||
что и начальный текст строки -
|
||||
Пример -
|
||||
|
||||
- длинная строка которая не может поместиться и будет перенесена по слову 'будет'
|
||||
|
||||
Должно отображаться так -
|
||||
- длинная строка которая не может поместиться и
|
||||
будет перенесена по слову 'будет'
|
||||
|
||||
Незакрытые модификаторы типа (bold/etc.) не переносят свою модификацию не последующие пункты списка.
|
||||
Действуют только в пределах одного пункта.
|
||||
(то есть фактически - пункт списка - это отдельный параграф но следующий пункт списка (тоже отдельный
|
||||
параграф) не отделяется от него пустой строкой.
|
||||
Вложенные списки - поддерживаются.
|
||||
Для отображения префиксов пунктов списка используется свой стиль. Так же для текста списков используется
|
||||
отдельный (от обычного текста) стиль.
|
||||
|
||||
Блок Кода -
|
||||
|
||||
Весь блок кода отображается только одним стилем - стилем Кода. В нем не действуют модификаторы
|
||||
bold/italic/etc (возможно в дальнейшей использование парсера языка для кода что бы отобразить
|
||||
этот код с подсветкой синтаксиса этого языка, но сейчас весь блок рисуется только одним стилем)
|
||||
После блока кода - обязательна пустая строка.
|
||||
Тип переноса строк - UnWrap. - То есть строки НЕ ПЕРЕНОСЯТСЯ.
|
||||
|
||||
Quoted -
|
||||
|
||||
Отображается как отдельный параграф. Перед отображением текста отображается символ префикса Цитирования
|
||||
Способы переноса текста аналогичны обычному тексту, за исключение того что перенесенные строки так же
|
||||
предваряются префиксом Цитирования
|
||||
Для отображения префиксов Цитирования используется свой стиль. Так же для текста цитирования используется
|
||||
отдельный (от обычного текста) стиль.
|
||||
Тип переноса строк - Wrap.
|
||||
Пример форматирования -
|
||||
|
||||
> Первый параграф
|
||||
>
|
||||
> Второй параграф
|
||||
> > Вложенный параграф
|
||||
>
|
||||
> Продолжение основной цитаты - длинная строка (переносится по слову 'строка')
|
||||
|
||||
Будет отображаться так -
|
||||
| Первый параграф
|
||||
|
|
||||
| Второй параграф
|
||||
| | Вложенный параграф
|
||||
|
|
||||
| Продолжение основной цитаты - длинная
|
||||
| строка (переносится по слову 'строка')
|
||||
|
||||
|
||||
Таблицы -
|
||||
|
||||
Пока отображаются as is.
|
||||
Дальше возможно предусмотрим вариант вычисления ширины столбцов и форматирование
|
||||
вывода что бы все ячейки столбца имели одинаковую ширину.
|
||||
Тип переноса строк - UnWrap.
|
||||
|
||||
Типы переноса строк -
|
||||
|
||||
Wrap -
|
||||
|
||||
происходит перенос текста с одной строки на другую по разделителям пробелам (предусмотреть
|
||||
во второй версии возможность использовать разделителем знаков точка, запятая, восклицательный
|
||||
знак, вопросительный знак, дефис. Замечание - новая строка не может начинаться со знаков
|
||||
разделителей - то есть если у нас идет многоточие (три точки) то нельзя что бы одна точка
|
||||
была в конце первой строки а остальные две на другой - если идут несколько разделителей подряд
|
||||
то они считаются как один и должны оставаться на первой строке).
|
||||
|
||||
UnWrap -
|
||||
|
||||
Текст НЕ ПЕРЕНОСИТСЯ.
|
||||
Если строка не помещается на экране - то в конец строки на экране выводим символ-знак наличия
|
||||
продолжения строки справа за краем экрана (свой стиль для этого символа).
|
||||
Символ '>'.
|
||||
Если есть хотя бы одна строка которая не помещается на экране - то разрешаем горизонтальный
|
||||
скроллинг.
|
||||
ЗАМЕЧАНИЕ - скроллируется только текст выводящийся в режиме UnWrap.
|
||||
Если произведен скроллинг влево (строки UnWrap начинаются показываться не с первой позиции)
|
||||
то на первой позиции отображем другой символ '<' сообщающий пользователю что есть текст
|
||||
за левым краем экрана.
|
||||
Скроллирование не бесконечно - если на экране нет строк UnWrap для которых есть скрытый текст
|
||||
за правым краем экрана то скроллирование влево больше не возможно, и наоборот - если при
|
||||
скроллировании вправо дошли до показа строк UnWrap с первой позиции то дальше скроллинг в этом
|
||||
направлении так же невозможен. Скроллинг идет с грануляцией по 8 символов.
|
||||
(сейчас UnWrap текст это только блоки кода и таблицы).
|
||||
|
||||
|
||||
Проанализируй данную постановку задачи.
|
||||
|
||||
Что требуется -
|
||||
|
||||
Мы более не поддерживаем два режима показа - Wrap/UnWrap - только один (смешанный).
|
||||
Потому вопрос - надо ли нам сохранять оригинальный контент считанного файла с диска ?
|
||||
Или при подготовке данных считываемых с диска можно сразу преобразовывать его в формат
|
||||
готовый для показа (объединять строки в одном параграфе и так далее) ?
|
||||
Ограничения - не забывать о том что это все работает на компьютере с 8-ми битным процессором.
|
||||
Потому очень экономно относимся к памяти и лишней работе процессора - все должно быть весьма
|
||||
быстрым и компактным.
|
||||
Требования для работы с файлами 128 Кб сохраняется.
|
||||
|
||||
Для версии 2 -
|
||||
Подумай о возможности использования банков памяти не только для содержимого файла а например
|
||||
для буферов типа line_offset/init_style и прочих (тогда их размер может так же быть динамическим
|
||||
и чем больше банков памяти будет использовано для чтения файла тем больше станут размеры этих
|
||||
буферов.
|
||||
Reference in New Issue
Block a user