737c974400
- Split tests/ (libc feature tests) and examples/ (real apps); shared
app.mk in repo root, was examples/example.mk
- libc/io/* split into libc/{conio,env,errno,file,mouse,string,sys,
time,video}/ — clearer module boundaries
- New examples/mdview/: markdown viewer (Phases 1-5 + light nested
lists). Headers (H1-H4), HR, ulist/olist/quote with nesting via
leading spaces, fenced code blocks, inline emphasis (bold/italic/
underscore/code), wrap/unwrap mode with soft wrap (F2), horizontal
pan (← →) with '>' truncation indicator
- libc additions: scroll() in conio (ESTEX SCROLL), strlwr/strupr,
gets() test
- Makefile updates across tests/ for the new shared app.mk path
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
528 lines
22 KiB
Markdown
528 lines
22 KiB
Markdown
# �« : ⥪áâ®¢ë© Markdown viewer ¤«ï Sprinter (`examples/mdview`)
|
||
|
||
## Context
|
||
|
||
’¥á⮢ ï ªàã¯ ï § ¤ ç - ¯à®¢¥à¨âì èã libc ¥âਢ¨ «ì®¬ interactive-¯à¨«®¦¥¨¨ (¯®«®íªà ë© UI, ä ©«®¢ë© I/O, ¯ àá¥à). � à ««¥«ì® ¤ áâ å®à®è¨© showcase ¯« âä®à¬ë ¨ ¯®¬®¦¥â ¢ëâ é¨âì ¥¤®¤¥«ª¨ ¢ conio/io. Š®¥ç ï æ¥«ì: viewer ¤«ï `.md` ä ©«®¢ á ¯®¤á¢¥âª®© á¨â ªá¨á , ¢¨£ 樥© ¯® ⥪áâã ¨ ¯®áâà ¨çë¬ áªà®««¨£®¬.
|
||
|
||
**Ž£à ¨ç¥¨ï v1 (§ 䨪á¨à®¢ ë ¯®«ì§®¢ ⥫¥¬):**
|
||
- POSIX file API (`open/read/lseek/close`); FILE*/fread/fgets - ¥ ¨á¯®«ì§®¢ âì
|
||
- Œ ªá¨¬ã¬ 16 KB ®¤¨ ä ©« (®¤ EMM-áâà ¨æ ); ¬®£®áâà ¨çë© à¥¦¨¬ - ¢ v2
|
||
- �®¤á¢¥âª ç¥à¥§ 梥â: **à §¬¥à § £®«®¢ª ** > 梥â èà¨äâ ; **bold/italic** > 梥â ä® (¬®®è¨à¨ë© ä®â ¡¥§ ¦¨à®£®/ªãàᨢ®£® ç¥àâ ¨ï)
|
||
|
||
---
|
||
|
||
## €àå¨â¥ªâãà
|
||
|
||
### � ᪫ ¤ª íªà (80x32, ⥪áâ mode 0x03)
|
||
|
||
```
|
||
Row 0: ³ mdview.md L 1-30 / 142 21% ³ < status bar (BG=blue, FG=white)
|
||
Row 1: ³ ³
|
||
... ³ document viewport (30 rows) ³
|
||
Row 30: ³ ³
|
||
Row 31: ³ F1 Help F10 Exit³ < menu bar (BG=blue, FG=cyan)
|
||
```
|
||
|
||
- Viewport = 30 áâப x 80 á⮫¡æ®¢.
|
||
- Status / menu ।¥àïâáï ç¥à¥§ `wrchar()` (¡¥§ ¢â®-áªà®«« ), viewport - ç¥à¥§ `LOCATE` + ¯®á¨¬¢®«ìë© `wrchar()` (⮦¥ ¡¥§ ¢â®-áªà®«« , áâ ¢¨â ¨ char ¨ attr § ®¤¨ call).
|
||
|
||
### � ¬ïâì
|
||
|
||
Memory mode: **`small`** - DSS ®â¢®¤¨â ¯®¤ è ®¡à § **¤¢ ¡ ª (W1 + W2)** = 32 KB á㬬 à® (CODE ¢ W1, DATA + STACK + HEAP ¢ W2). �⮣® ¤®«¦® å¢ â¨âì ç⮡ë �… § ¢®¤¨âì `__banked` äãªæ¨¨. W3 ®áâ ñâáï ¯®«®áâìî ᢮¡®¤ë¬ ¤«ï ¬ ¯¯¨£ ¡®«ìè¨å ¡ãä¥à®¢:
|
||
|
||
```
|
||
W0 (0x0000-0x3FFF): ESTEX (system, untouchable)
|
||
W1 (0x4000-0x7FFF): CODE (small mode page 1)
|
||
W2 (0x8000-0xBFFF): DATA + STACK + HEAP (small mode page 2)
|
||
W3 (0xC000-0xFFFF): paged window - ¯¥à¥ª«îç ¥âáï ¬¥¦¤ã EMM-áâà ¨æ ¬¨:
|
||
ÃÄÄ file page: ¨áå®¤ë© â¥ªáâ .md ä ©« (16 KB)
|
||
ÀÄÄ cache page: ªíè ®âä®à¬ â¨à®¢ ëå áâப (Phase 3+)
|
||
```
|
||
|
||
�®ç¥¬ã small + W3:
|
||
- 32 KB ª®¤+¤ ë¥ á ¡®«ì訬 § ¯ ᮬ > ¥â ¡ ª¨£
|
||
- W3 - áâ ¤ àâë© paged window, ¯®¤ ¥£® ã á 㦥 ¥áâì `bank_io_w3` API
|
||
- v2-à áè¨à¥¨¥ (multi-page ä ©«ë >16 KB): ¯à®áâ® `mem_alloc_pages(N)` ¨ ¯¥à¥ª«î票¥ áâà ¨æ ¢ W3 ç¥à¥§ `sprinter_page_w3()`
|
||
|
||
‘â ⨪¨ (¢ W2):
|
||
- `line_offset[MAX_LINES]` - uint16_t ᬥ饨¥ ª ¦¤®© áâப¨ ¢ ä ©«®¢®© áâà ¨æ¥ (4 KB 2048 áâப)
|
||
- `cache_tag[CACHE_N]` - uint16_t ⥣ á«®â (200 ¡ ©â 100 ᫮⮢, ¯®ï¢«ï¥âáï ¢ Phase 3)
|
||
- `filename[64]`, `top_line`, `total_lines`, `file_size`, `file_blk`, `cache_blk` - ¥¤¨¨æë ¡ ©â
|
||
|
||
**FILE_BUF**: `((char*)0xC000)` - 䨪á¨à®¢ ï ¤à¥á æ¨ï ¢ W3 ¯®á«¥ ¬ ¯¯¨£ 㦮© áâà ¨æë.
|
||
|
||
### �®â®ª ¤ ëå
|
||
|
||
```
|
||
main > open() > read() chunks 1KB > write to W1 (mapped EMM page) > close()
|
||
> index_lines() (®¤® ᪠¨à®¢ ¨¥, § ¯®«ï¥â line_offset[])
|
||
> render_viewport() + main loop { getkey(); handle(); render_status(); render_viewport() }
|
||
```
|
||
|
||
**’®ª®áâì á `read()`**: ESTEX READ § ¯¨áë¢ ¥â ¯® dst-㪠§ â¥«î ¢ ¤à¥á®¬ ¯à®áâà á⢥ ¢ë§ë¢ î饣®. �®áª®«ìªã ¬ë ¬ ¯¯¨¬ EMM-áâà ¨æã ¢ W3 (0xC000) „Ž ¢ë§®¢ read(), 㪠§ ⥫ì 0xC000+offset ¢ «¨¤¥. …᫨ ¢ëïá¨âáï çâ® BIOS âண ¥â W3 ¢® ¢à¥¬ï read (£à ä¨ç¥áª¨© ¢¨¤¥®¡ãä¥à ¯® 㬮«ç ¨î ¢ W3 ¯à¨ £à ä¨ç¥áª¨å ०¨¬ å, ® ¢ ⥪á⮢®¬ - ¤®«¦¥ ¡ëâì ᢮¡®¤¥) - fallback: ç¨â âì ¢ 1 KB ¡ãä¥à ¢ W2 ¨ ª®¯¨à®¢ âì ¢ W3 ç¥à¥§ `bank_write_w3()`.
|
||
|
||
---
|
||
|
||
## �¥ «¨§ æ¨ï - ¯®íâ ¯ ï
|
||
|
||
### Phase 1 - Plain text viewer (MVP)
|
||
|
||
**—â® à ¡®â ¥â:**
|
||
- ‡ £à㧪 ä ©« (`open/read/close`) ¢ W1-áâà ¨æã
|
||
- ˆ¤¥ªá æ¨ï áâப (LF / CRLF à §¤¥«¨â¥«¨)
|
||
- Status bar: ¨¬ï ä ©« , L N-M / Total, ¯à®æ¥â áªà®««¨£
|
||
- Menu bar: `F1 Help F10 Exit`
|
||
- � ¢¨£ æ¨ï: ^/v (1 áâப ), PgUp/PgDn (30 áâப), Home/End ( ç «®/ª®¥æ), Esc/F10 (¢ë室), F1 (help screen)
|
||
- Ž¡à¥§ª áâப ¤«¨¥¥ 80 ᨬ¢®«®¢ (¡¥§ word-wrap)
|
||
- –¢¥â : ⥪áâ ¡¥«ë© çñ஬; status/menu - ¡¥«ë© ᨥ¬
|
||
|
||
**Šà¨â¨çë¥ ä ©«ë:**
|
||
- `examples/mdview/mdview.c` - main, key loop, rendering, indexing (one-file MVP)
|
||
- `examples/mdview/Makefile`
|
||
- `examples/mdview/SAMPLE.MD` - â¥áâ®¢ë© markdown ä ©«
|
||
|
||
### Phase 2 - Headers ¨ £®à¨§®â «ì ï «¨¨ï
|
||
|
||
**MD ä¨ç¨:**
|
||
- `# H1` > ïમ-¦ñ«âë© (COLOR_YELLOW = 14) çñ஬
|
||
- `## H2` > ïમ-£®«ã¡®© (COLOR_LBLUE = 11)
|
||
- `### H3` > ïમ-§¥«ñë© (COLOR_LGREEN = 10)
|
||
- `#### H4+` > á¥àë© (COLOR_GREY = 8)
|
||
- `---` / `***` ®â¤¥«ì®© áâப¥ > «¨¨ï 0xC4 (£®à¨§®â «ì ï à ¬ª ASCII) ¢® ¢áî è¨à¨ã
|
||
|
||
### Phase 3 - Inline emphasis
|
||
|
||
**� àá¥à inline (per-line, runs ¢ ®¤ã áâபã):**
|
||
- `**bold**` > ATTR_TEXT_BOLD
|
||
- `*italic*` > ATTR_TEXT_ITALIC
|
||
- `_underscore_` > ATTR_TEXT_UNDERSORE
|
||
- `` `code` `` > ATTR_TEXT_CODE
|
||
- Œ થàë `**`/`*`/`_`/`` ` `` �… ।¥àïâáï (áꥤ îâáï)
|
||
|
||
State machine: ®¤¨ ªâ¨¢ë© áâ¨«ì ®¤®¢à¥¬¥® (¡¥§ ¢«®¦¥®áâ¨); ª®ä«¨ªâãî騩 ¬ àª¥à ¯à¨ ç㦮¬ ªâ¨¢®¬ á⨫¥ ã室¨â «¨â¥à «®¬. ‘®áâ®ï¨¥ á¡à áë¢ ¥âáï ª ¦¤®© áâப¥.
|
||
|
||
> **Šíè ®âä®à¬ â¨à®¢ ëå áâப** - ®â«®¦¥ ¢ á ¬ë© ª®¥æ, á¬. "Phase ?: ®¯â¨¬¨§ 樨".
|
||
> ‘ª®à®á⨠⥪ã饣® ¨¢®£® ।¥à å¢ â ¥â 80x30 = 2400 wrchar / ª ¤à; PgUp/PgDn ¢¨§ã «ì® ¬£®¢¥¥.
|
||
|
||
### Phase 4 - Block elements
|
||
|
||
- Œ ન஢ ë¥ á¯¨áª¨: `- foo`, `* foo`, `+ foo` > ¯à¥ä¨ªá `ù` (0x07) + ¯à®¡¥«; 梥⠬ થà ïàç¥ ®á®¢®£®
|
||
- �㬥஢ ë¥ á¯¨áª¨: `1. foo`, `2. foo` > ª ª ¥áâì (ç¨á«® ®áâ ¢«ï¥¬)
|
||
- Blockquote: áâப¨ á `> ` > ¯à¥ä¨ªá `³` (0xB3) á¥à®£® 梥â , ®á⠫쮩 ⥪áâ á«¥£ª ¯à¨£«ãèñë©
|
||
- Fenced code blocks: `` ``` `` ®âªàë¢ ¥â/§ ªàë¢ ¥â ¡«®ª; ¢á¥ áâப¨ ¬¥¦¤ã - bg=á¥àë©, ¬®®è¨à¨® (¡¥§ inline-¯ àᨣ )
|
||
- Indented code blocks (4+ ¯à®¡¥«®¢): «®£¨ç® fenced, ® ¡¥§ £® ¬ થà
|
||
|
||
**Light nested lists (v1 - ॠ«¨§®¢ ®):**
|
||
- `classify_line()` ¯à®¯ã᪠¥â leading spaces ¯¥à¥¤ ulist/olist/quote ¬ થ஬,
|
||
¢®§¢à é ¥â `content_off` ¯®á«¥ ¬ થà > `content_off - p_start` = indent + marker
|
||
¡¨â ¢ visible col.
|
||
- `render_line()` à¨áã¥â leading-spaces ¢ `ATTR_TEXT`, ¯®â®¬ ¬ થà ᤢ¨ã⮩
|
||
¯®§¨æ¨¨ (col = indent). Marker ¢áñ ¥éñ 䨪á¨à®¢ ¯à¨ £®à¨§®â «ì®¬ pan'¥.
|
||
- HR / header / fence delim ®áâ îâáï áâண® col-0 (CommonMark à §à¥è ¥â ¤® 3
|
||
¢¥¤ãé¨å ¯à®¡¥«®¢ ¤«ï ¨å - ã¯à®á⨫¨).
|
||
- Tab-indent > ¥ à ᯮ§ ñâáï ª ª nesting (⮫쪮 spaces).
|
||
|
||
**Phase 4-full - ¯®« ï ¯®¤¤¥à¦ª ¢«®¦¥®á⨠(deferred):**
|
||
- **Tab-indent**: áç¨â âì tab = 4 ¯à®¡¥« ¤«ï ®¯à¥¤¥«¥¨ï ã஢ï.
|
||
- **Quote nesting** (`> > foo`): ª ¦¤ë© `>` ¯®¤àï¤ = +1 ã஢¥ì, ª ¦¤ë© à¨áã¥âáï
|
||
®â¤¥«ìë¬ `³` ¢ `ATTR_QUOTE_MARKER` (¢¨§ã «ì ï "«¥áâ¨æ " á«¥¢ ).
|
||
- **Hanging indent ¢ wrap-continuation**: ª®£¤ `- some very long bullet text
|
||
that wraps...` - continuation seg ¤®«¦¥ ç¨ âìáï ®â content-col (¯®á«¥
|
||
¬ થà ), ¥ ®â col 0. ‘¥©ç á continuation ¨¤ñâ ®â col 0 (v1 simplification).
|
||
’ॡã¥â åà ¨âì `marker_width` per «®£¨ç¥áª ï áâப (8 ¡¨â) ¨«¨ re-classify
|
||
first seg ¯à¨ ।¥à¥ continuation.
|
||
- **Lazy continuation**: áâப¨ ¡¥§ ¬ થà , ® á ¯à ¢¨«ìë¬ indent ¯®¤
|
||
¯à¥¤ë¤ã騬 bullet'®¬, ¤®«¦ë áç¨â âìáï ¯à®¤®«¦¥¨¥¬ ⮣® bullet'
|
||
(¢¨§ã «ì® - ®¡é¨© attr).
|
||
- **Strict CommonMark indent rules**: ¢«®¦¥ë© ¯ãªâ ¤®«¦¥ ¡ëâì indent
|
||
? content_col த¨â¥«ï, ¨ ç¥ áç¨â ¥âáï breakout. �㦥 ¬¨¨-stack
|
||
ªâ¨¢ëå ᯨ᪮¢ ¯à¨ ¨¤¥ªá 樨.
|
||
|
||
### Phase 5 - Wrap / Unwrap ¤«¨ëå áâப
|
||
|
||
„¥ä®«â: **wrap on**. F2 ¯¥à¥ª«îç ¥â; ¢ ¬¥î-¡ ॠ¯®¤¯¨áì ®âà ¦ ¥â ¤¥©á⢨¥
|
||
("Unwrap" ª®£¤ wrap ¢ª«îçñ, "Wrap" ª®£¤ ¢ëª«îç¥).
|
||
|
||
**v1 - ॠ«¨§®¢ ®:**
|
||
- ޤ¨ ¬ áᨢ `line_offset[2048]` åà ¨â ‚ˆ„ˆŒ›… ᥣ¬¥âë ( ¥ «®£¨ç¥áª¨¥
|
||
áâப¨); ¡¨âë 0..13 - ¡ ©â®¢®¥ ᬥ饨¥, ¡¨â 15 - CONT-ä« £ continuation.
|
||
- Wrap-०¨¬: soft wrap ¯®á«¥¤¥¬ ¯à®¡¥«¥ ? 80; hard fallback ¥á«¨
|
||
¯à®¡¥« ¥â.
|
||
- Œ થàë í¬ä §¨á (`**`/`*`/`_`/`` ` ``) ¨ header-¯à¥ä¨ªáë (`#`/`##`/...) ¥
|
||
ãç¨âë¢ îâáï ¢ visible-col ¯à¨ ¯®¨áª¥ â®çª¨ ¯¥à¥®á .
|
||
- "‘¯¥æ¨ «ìë¥" «®£¨ç¥áª¨¥ áâப¨ ¥ wrap' îâáï ¢®®¡é¥ (®¤ seg-§ ¯¨áì
|
||
«®£¨ç¥áªãî áâபã): fence delim, table row (header/separator/body), HR.
|
||
- F2 toggle á®åà ï¥â ¢¨§ã «ìãî ¯®§¨æ¨î ç¥à¥§ `top_offset` ¢ FILE_BUF.
|
||
- Bitmaps (`in_code`/`in_table`/`is_tab_hdr`) ¯¥à¥áâà ¨¢ îâáï ¢¬¥á⥠á
|
||
ᥣ¬¥â ¬¨, ¨¤¥ªá¨àãîâáï seg-¨¤¥ªá®¬, ¡¨âë áâ ¢ïâáï ⮫쪮 ¯¥à¢®¬
|
||
seg'¥ «®£¨ç¥áª®© áâப¨.
|
||
- Continuation-ᥣ¬¥âë ।¥àïâáï ¢ á⨫¥ "v1: ¯«®áª®" - plain text,
|
||
¨ª ª¨å markdown-ª« áá¨ä¨ª 権; padding ¤® ª®æ áâப¨ `ATTR_TEXT`.
|
||
|
||
**v1.5 - ®â«®¦¥® ¤«ï ¯®«®© ª àâ¨ë wrap:**
|
||
- **Hanging indent**: continuation ®â ulist/olist/quote ¤®«¦¥ ¢ëà ¢¨¢ âìáï
|
||
¯®¤ content, ¥ ®â col 0. ’ॡã¥â åà ¨âì marker_width per «®£¨ç¥áª ï
|
||
áâப ˆ‹ˆ re-classify ¯¥à¢®£® seg' ¯à¨ ।¥à¥ continuation.
|
||
- **� á«¥¤®¢ ¨¥ base_attr**: continuation ®â header' ¤®«¦¥ á®åà ïâì
|
||
梥â; continuation ®â code body - ä® ATTR_TEXT_CODE. ’ॡã¥â åà ¨âì
|
||
1 ¡ ©â `base_attr` per seg ˆ‹ˆ lookup ¯¥à¢®£® seg' .
|
||
- **Inline emphasis ç¥à¥§ £à ¨æã**: í¬ä §¨á, ®âªàëâë© ¢ ¯¥à¢®¬ seg'¥ ¨ ¥
|
||
§ ªàëâë©, ¤®«¦¥ ¯à®¤®«¦ âìáï ¢® ¢â®à®¬. ’ॡã¥â åà ¨âì emph state per
|
||
seg (3 ¡¨â ).
|
||
- Compact way: ¤®¡ ¢¨âì ¯ à ««¥«ìë© ¬ áᨢ `seg_meta[MAX_SEGS]` ¯® 1 ¡ ©âã
|
||
- ¯ ªã¥â marker_width (4 ¡¨â ) + emph_state (3 ¡¨â ) + base_attr_idx
|
||
(4 ¡¨â ¨§ â ¡«¨æë > 㦥 2-¡ ©â®¢ë© seg_meta).
|
||
- **Hpan ¤«ï ¤«¨ëå áâப**: ¥á«¨ wrap ¢ëª«îç¥, ¤®¡ ¢¨âì </> ¤«ï
|
||
£®à¨§®â «ì®£® áªà®«« >80 cols. ޡ鍩 ¬¥å ¨§¬ á tables (Phase 6).
|
||
**�…€‹ˆ‡Ž‚€�Ž** (light) - `viewport_x` + ¯®«ë© re-render ª ¦¤®¥ </>.
|
||
- **“᪮२¥ hpan ç¥à¥§ ESTEX WINCOPY/WINREST** (deferred): ᥩç á pan
|
||
¤¥« ¥â ¯®«ë© `render_viewport()` = 30 áâப x 80 wrchar. Œ®¦®
|
||
᪮¯¨à®¢ âì áãé¥áâ¢ãî饥 ᮤ¥à¦¨¬®¥ viewport' N cols ¢«¥¢®/¢¯à ¢®
|
||
ç¥à¥§ win-copy, ¯®â®¬ ।¥à¨âì ⮫쪮 㧪ãî ¯®«®áã á¯à ¢ /á«¥¢
|
||
(HPAN_STEP cols x 30 rows ~ 240 wrchar ¢¬¥áâ® 2400). ESTEX SCROLL
|
||
£®à¨§®â «ì ¥ ¯®¤¤¥à¦¨¢ ¥â - 㦠¨¬¥® WINCOPY-®¯¥à æ¨ï ¨«¨
|
||
rdchar/wrchar loop. €ªâ¨¢¨à®¢ âì ª®£¤ ®éãâ¨âáï â®à¬®§; ᥩç á
|
||
⨯®¢®¬ markdown'¥ ¥ § ¬¥â®.
|
||
|
||
**v2 - ®â¤¥«ì ï ä¨ç , ¬¨¬® wrap:**
|
||
- Toggle ¯®¤á¢¥âª¨ 楫¨ª®¬ (F3?)
|
||
- Search ¯® ⥪áâã (Ctrl+F / F4)
|
||
- Links `[text](url)` > ᨨ© ¯®¤çñàªãâë© text, url ¯àïç¥âáï
|
||
- Images `` > `[IMG: alt]`
|
||
|
||
### Phase 7 - Links ¨ ¯®¨áª (post-v1)
|
||
|
||
- `[text](url)` > ®âà¨á®¢ âì ⮫쪮 `text` á ïમ-ᨨ¬ FG (¢¨§ã «ì® ¯®¤çñàªã⮥)
|
||
- `` > `[IMG: alt]` ¢ ᪮¡ª å
|
||
- Search ¯® ⥪áâã (F3 / Ctrl+F): ¨ªà¥¬¥â «ìë©, ¯®¤á¢¥âª ᮢ¯ ¤¥¨©
|
||
|
||
### Phase 8 - F8 Raw / Render toggle
|
||
|
||
�¥à¥ª«îç ⥫ì ०¨¬ ®â®¡à ¦¥¨ï: ¯à¨ ¢ª«îçñ®¬ Raw ¯®ª §ë¢ ¥âáï ¨á室ë©
|
||
⥪áâ ä ©« ª ª ¥áâì - ¢á¥ markdown-¬ થàë (`#`, `**`, `_`, `` ` ``, `|`,
|
||
`>`, `-`, etc.) ।¥àïâáï «¨â¥à « ¬¨ á `ATTR_TEXT`, ¡¥§ ª« áá¨ä¨ª 樨.
|
||
�®«¥§® ª®£¤ :
|
||
- 㦮 㢨¤¥âì â®çãî à §¬¥âªã (®â« ¦¨¢ ¨¥ .md, áªà¨è®âë, ª®¯¨à®¢ ¨¥)
|
||
- markdown-ª« áá¨ä¨ª â®à ®è¨¡áï ¨ å®ç¥âáï 㢨¤¥âì ®à¨£¨ «
|
||
- å®ç¥âáï ¡ëáâà® áà ¢¨âì "¤®/¯®á«¥" ।¥à
|
||
|
||
**�®¢¥¤¥¨¥:**
|
||
- F8 ¯¥à¥ª«îç ¥â `render_mode` (1=render, 0=raw); ¬¥î ¯®ª §ë¢ ¥â ®¡à ⮥
|
||
¤¥©á⢨¥ ("Raw" ª®£¤ ᥩç á render, "Render" ª®£¤ ᥩç á raw) - ⮩ ¦¥
|
||
«®£¨ª®© çâ® F2/Wrap/Unwrap.
|
||
- ‚ Raw ०¨¬¥: `render_line()` ¨¤ñâ ¯® ª®à®âª®¬ã ¯ã⨠- ¨ª ª®£®
|
||
`classify_line`, `is_fence_delim`, `is_code_body`, inline-í¬ä §¨á ; ¯à®áâ®
|
||
¡ ©â®¢ë© ¤ ¬¯ FILE_BUF ®â seg-offset ¤® next-seg/EOL á tab-expansion ¨
|
||
ATTR_TEXT.
|
||
- � §¤¥«ì® ®â F2: ®¡ ०¨¬ ¥§ ¢¨á¨¬ë (¬®¦® Raw+Wrap, Raw+Truncate,
|
||
Render+Wrap, Render+Truncate). Wrap-«®£¨ª ¢ `index_lines` à ¡®â ¥â ¢
|
||
®¡®¨å á«ãç ïå ®¤¨ ª®¢® (®¯¨à ¥âáï ¢¨§ã «ìë¥ ª®«®ª¨ ¥§ ¢¨á¨¬® ®â
|
||
à áªà ᪨).
|
||
- ‘â âãá-¡ à: ¤®¡ ¢¨âì ¨¤¨ª â®à `[R]` / `[V]` (Raw / View) ¨«¨ ⥪á⮬
|
||
`RAW` à冷¬ á ¨¬¥¥¬ ä ©« .
|
||
|
||
**Œ¨¨¬ «ì ï ॠ«¨§ æ¨ï:**
|
||
- ޤ¨ ®¢ë© static `uint8_t render_mode = 1;`
|
||
- ‚ `render_line()`: á ¬®¬ ¢¥àåã `if (!render_mode) { ? raw render ? return; }`
|
||
- ‚ `render_menu()`: ¤®¡ ¢¨âì ïà«ëª F8 à冷¬ á F2.
|
||
- ‚ £« ¢®¬ 横«¥: `case KEY_F8: toggle_render(); break;`
|
||
- `toggle_render()` ®â«¨ç ¥âáï ®â `toggle_wrap()` ⥬, çâ® �… ¯¥à¥áâà ¨¢ ¥â
|
||
`line_offset[]` (wrap-ᥣ¬¥â æ¨ï ¥ ¬¥ï¥âáï), ⮫쪮 ¯¥à¥à¥¤¥à¨â íªà .
|
||
|
||
---
|
||
|
||
## API-®¢¨ª¨ ¢ libc (¬¨¨¬ «ìë¥)
|
||
|
||
### `getkey()` - extended key reader (¢ libc)
|
||
|
||
’¥ªã騩 `getch()` â¥àï¥â scan code à áè¨à¥ëå ª« ¢¨è (¢®§¢à é ¥â ⮫쪮 E=ASCII). „®¡ ¢«ï¥¬ **áà §ã ¢ `libc/conio/conio.c`** ®¢ãî äãªæ¨î à冷¬ á `getch()`:
|
||
|
||
```c
|
||
// Returns scan in high byte, ASCII in low byte.
|
||
// Extended keys (arrows, F-keys, PgUp/PgDn, Home/End): ASCII=0, scan code ¢ high byte.
|
||
// Plain keys: ASCII ¢ low byte; high byte ᮤ¥à¦¨â positional scan (¡¨â 7 = Ctrl/Alt/Shift modifier).
|
||
uint16_t getkey(void) __naked {
|
||
__asm
|
||
ld c, #0x30 ; ESTEX WAITKEY
|
||
rst #0x10 ; A=ASCII, D=scan, E=ASCII
|
||
ld e, a ; ensure E=ASCII even if E clobbered
|
||
ret ; SDCC __sdcccall(1): ¢®§¢à â uint16_t ¢ DE (D=scan, E=ASCII)
|
||
__endasm;
|
||
}
|
||
```
|
||
|
||
„®¯®«¨â¥«ì® - **¢ `libc/include/conio.h`** ¯à®¯¨á âì ¯à®â®â¨¯ ¨ ª®áâ âë scan-ª®¤®¢:
|
||
|
||
```c
|
||
uint16_t getkey(void);
|
||
|
||
/* Scan codes for getkey() high byte when ASCII=0 (extended keys). */
|
||
#define KEY_F1 0x0E
|
||
#define KEY_F2 0x0F
|
||
#define KEY_F3 0x10
|
||
#define KEY_F4 0x11
|
||
#define KEY_F5 0x12
|
||
#define KEY_F6 0x13
|
||
#define KEY_F7 0x14
|
||
#define KEY_F8 0x15
|
||
#define KEY_F9 0x16
|
||
#define KEY_F10 0x17
|
||
#define KEY_F11 0x18
|
||
#define KEY_F12 0x19
|
||
#define KEY_END 0x24
|
||
#define KEY_DOWN 0x25
|
||
#define KEY_PGDN 0x26
|
||
#define KEY_LEFT 0x27
|
||
#define KEY_RIGHT 0x29
|
||
#define KEY_HOME 0x2A
|
||
#define KEY_UP 0x2B
|
||
#define KEY_PGUP 0x2C
|
||
#define KEY_INS 0x23
|
||
#define KEY_DEL 0x22
|
||
```
|
||
|
||
**‘ª -ª®¤ë (¨§ docs/converted/ProgrammerManual.txt:2143-2323):**
|
||
| Š« ¢¨è | scan | Š« ¢¨è | scan |
|
||
|---|---|---|---|
|
||
| F1 | 0x0E | Up | 0x2B |
|
||
| F10 | 0x17 | Down | 0x25 |
|
||
| F11 | 0x18 | Left | 0x27 |
|
||
| F12 | 0x19 | Right | 0x29 |
|
||
| | | PgUp | 0x2C |
|
||
| | | PgDn | 0x26 |
|
||
| | | Home | 0x2A |
|
||
| | | End | 0x24 |
|
||
|
||
### —â® **¯¥à¥¨á¯®«ì§ã¥¬** ¨§ áãé¥áâ¢ãî饩 libc
|
||
|
||
- `open/read/lseek/close` - `libc/io/{open,read,lseek}.c` (POSIX wrappers)
|
||
- `mem_alloc_pages/mem_free_block/mem_get_page` - `libc/mem/mem_alloc.c`
|
||
- `sprinter_page_w3()` - inline `__sfr` write ¢ `libc/include/sprinter.h:113`
|
||
- `bank_read_w3/bank_write_w3` - `libc/mem/bank_io_w3.c` (¤«ï fallback ¨«¨ v2 multi-page)
|
||
- `wrchar(x, y, ch, attr)` - `libc/conio/conio.c:476` (¡¥§ auto-scroll, ¨¤¥ «ì® ¤«ï viewport)
|
||
- `clrscr_attr(attr)` - `libc/conio/conio.c:395`
|
||
- `gotoxy/wherex/wherey` - `libc/conio/conio.c:412-462` (¥á«¨ 㦮)
|
||
- `kbhit()` - `libc/conio/conio.c:22` (¤«ï non-blocking ®¯à®á , ®¯æ¨® «ì®)
|
||
- `dec16/dec8` - `libc/stdio/dec_print.c` (¤«ï status bar: ⥪ãé ï áâப / total / %)
|
||
- `COLOR(fg, bg)` ¬ ªà®á - `libc/include/conio.h:152`
|
||
- –¢¥â®¢ë¥ ª®áâ âë `COLOR_*` - `libc/include/conio.h:145`
|
||
- `strlen/memcpy/memset` - z80.lib (�… ¯¥à¥¯¨áë¢ âì)
|
||
|
||
---
|
||
|
||
## ‘âàãªâãà ¨á室¨ª®¢
|
||
|
||
```
|
||
examples/mdview/
|
||
ÃÄÄ Makefile # áâ ¤ àâë© pattern (á¬. examples/cat/Makefile)
|
||
ÃÄÄ mdview.c # Phase 1: ¢áñ ¢ ®¤®¬ ä ©«¥ (main, keys, indexing, render)
|
||
ÃÄÄ SAMPLE.MD # â¥áâ®¢ë© markdown
|
||
ÀÄÄ README.md # ®¯¨á ¨¥ ¨ controls
|
||
```
|
||
|
||
�®á«¥ Phase 3 à ᪨¤ âì ¯® ¬®¤ã«ï¬ (¥á«¨ á㬬 àë© à §¬¥à > ~6KB):
|
||
```
|
||
mdview.c - main loop, status/menu bars, key dispatch
|
||
mdrender.c - line rendering with MD inline parser
|
||
mdindex.c - file load + line indexing
|
||
```
|
||
|
||
### ‘¡®àª
|
||
|
||
```makefile
|
||
PROJ ?= ../..
|
||
SPRINTER_CC := $(PROJ)/bin/sprinter-cc
|
||
mdview.exe: mdview.c
|
||
$(SPRINTER_CC) --memory small -o $@ mdview.c
|
||
```
|
||
|
||
`--memory small`: ª®¤+¤ ë¥ ¢ W2 (DSS ¤ ñâ 㦮¥ ç¨á«® áâà ¨æ); ä ©« - ®â¤¥«ì ï EMM-áâà ¨æ ¢ W3.
|
||
|
||
---
|
||
|
||
## ‘âàãªâãà mdview.c (Phase 1, í᪨§)
|
||
|
||
```c
|
||
#include <stdint.h>
|
||
#include <stdio.h>
|
||
#include <conio.h>
|
||
#include <fcntl.h>
|
||
#include <unistd.h>
|
||
#include <sprinter.h>
|
||
#include <sprinter_mem.h>
|
||
|
||
#define VIEW_TOP 1
|
||
#define VIEW_BOT 30 // inclusive
|
||
#define VIEW_H 30
|
||
#define SCREEN_W 80
|
||
#define MAX_LINES 2048
|
||
#define FILE_BUF ((char*)0xC000) /* W3 - EMM page mapped here */
|
||
#define TAB_STOP 4
|
||
|
||
#define ATTR_TEXT COLOR(COLOR_WHITE, COLOR_BLACK)
|
||
#define ATTR_BAR COLOR(COLOR_WHITE, COLOR_BLUE)
|
||
#define ATTR_MENU_K COLOR(COLOR_YELLOW, COLOR_BLUE)
|
||
#define ATTR_MENU_T COLOR(COLOR_WHITE, COLOR_BLUE)
|
||
|
||
static uint16_t line_off[MAX_LINES];
|
||
static uint16_t n_lines;
|
||
static uint16_t top_line;
|
||
static uint16_t file_size;
|
||
static uint8_t file_blk;
|
||
static char filename[64];
|
||
|
||
static int load_file(const char *path); // open, alloc EMM page, map W3, read, close
|
||
static void index_lines(void); // scan FILE_BUF, fill line_off[]
|
||
static void render_status(void); // row 0
|
||
static void render_menu(void); // row 31
|
||
static void render_line(uint16_t idx, uint8_t row); // one line @ row
|
||
static void render_viewport(void); // VIEW_H lines starting from top_line
|
||
static void scroll_up(uint16_t n);
|
||
static void scroll_down(uint16_t n);
|
||
static void help_screen(void); // F1
|
||
|
||
int main(int argc, char **argv) {
|
||
if (argc < 2) { puts("Usage: mdview <file.md>"); return 1; }
|
||
if (load_file(argv[1]) < 0) { puts("load error"); return 1; }
|
||
index_lines();
|
||
clrscr_attr(ATTR_TEXT);
|
||
render_menu();
|
||
render_status();
|
||
render_viewport();
|
||
for (;;) {
|
||
uint16_t k = getkey();
|
||
uint8_t ascii = k & 0xFF;
|
||
uint8_t scan = (k >> 8) & 0x7F; // strip mod bit
|
||
if (ascii) {
|
||
if (ascii == 0x1B) break; // Esc > exit
|
||
continue;
|
||
}
|
||
switch (scan) {
|
||
case KEY_F10: goto exit;
|
||
case KEY_F1: help_screen(); break;
|
||
case KEY_UP: scroll_up(1); break;
|
||
case KEY_DOWN: scroll_down(1); break;
|
||
case KEY_PGUP: scroll_up(VIEW_H); break;
|
||
case KEY_PGDN: scroll_down(VIEW_H); break;
|
||
case KEY_HOME: top_line = 0;
|
||
render_viewport(); break;
|
||
case KEY_END: /* clamp to last viewport */ break;
|
||
}
|
||
render_status();
|
||
}
|
||
exit:
|
||
mem_free_block(file_blk);
|
||
clrscr_attr(ATTR_TEXT);
|
||
return 0;
|
||
}
|
||
```
|
||
|
||
---
|
||
|
||
## Verification
|
||
|
||
### Phase 1
|
||
1. �®¤£®â®¢¨âì `SAMPLE.MD` ~5 KB (§ £®«®¢ª¨, ¡§ æë, ᯨ᪨) - ।¥à¨âìáï ¡ã¤¥â plain.
|
||
2. `cd examples/mdview && make`
|
||
3. `python make_disk.py mdview.exe SAMPLE.MD > mc.img && ./run_mame.sh`
|
||
4. �஢¥à¨âì:
|
||
- Status bar ¯®ª §ë¢ ¥â `SAMPLE.MD L 1-30 / N X%`
|
||
- Menu bar ¢¨§ã
|
||
- ^/v: 1 áâப
|
||
- PgUp/PgDn: 30 áâப, ª®à४⮥ clamp £à ¨æ å
|
||
- Home: top_line=0
|
||
- End: top_line = total_lines - VIEW_H
|
||
- F1: ¯®ª §ë¢ ¥â help, «î¡ ï ª« ¢¨è ¢®§¢à é ¥â
|
||
- F10 / Esc: ¢ë室, íªà ®ç¨é¥
|
||
5. Edge cases: ¯ãá⮩ ä ©«, ä ©« ¨§ ®¤®© áâப¨, ä ©« á ®ç¥ì ¤«¨®© áâப®© (>80), CRLF ¨ LF mixed.
|
||
|
||
### Phase 2-4
|
||
� áè¨àïâì `SAMPLE.MD` á ä¨ç ¬¨ ¯® ¬¥à¥ ¤®¡ ¢«¥¨ï, ¢¨§ã «ì® ¢¥à¨ä¨æ¨à®¢ âì ¢ MAME. ‘ªà¨è®â-áà ¢¥¨¥ ®¯æ¨® «ì®.
|
||
|
||
### �¥£à¥áᨨ
|
||
- �¨ª ª¨å ¨§¬¥¥¨© ¢ libc Phase 1 ªà®¬¥ (¯®â¥æ¨ «ì®) ¤®¡ ¢«¥¨ï `getkey()` ¢ `libc/conio/conio.c` - ¥á«¨ â ª, ¯à®£ âì `examples/conio2` ¨ `examples/filetest` ç⮡ë ã¡¥¤¨âìáï çâ® ¨ç¥£® ¥ á«®¬ «®áì.
|
||
|
||
---
|
||
|
||
## �¥è¥¨ï ¯® ¥®¤®§ ç®áâï¬
|
||
|
||
1. **Word-wrap vs truncate**: v1 = truncate (¯à®áâ®). v2 - F2 toggle wrap.
|
||
2. **ƒ®à¨§®â «ìë© áªà®««¨£**: v1 - ¥â; v2 - `</>` ᤢ¨£ viewport ¯® á⮫¡æ ¬.
|
||
3. **Tab handling**: ¯à¥®¡à §®¢ ¨¥ ¯à¨ ।¥à¥, **tabstop = 4** (áâ ¤ àâ MD). Žà¨£¨ « ¢ W3 ¥ âண ¥¬.
|
||
4. **UTF-8**: ।¥à¨¬ ¡ ©âë ª ª ¥áâì. …᫨ ä ©« ¢ CP866 - ®âà¨áã¥âáï ª¨à¨««¨æ¥© ç¥à¥§ á¨áâ¥¬ë© ä®â. UTF-8 - ¯®ª ¥ ¯®¤¤¥à¦¨¢ ¥¬ (¢¨§ã «ì® ¡ã¤¥â ª è ¥-ASCII ᨬ¢®« å; ¤¥â¥ªâ ¨ ¯à¥¤ã¯à¥¦¤¥¨¥ - ¢ v2).
|
||
|
||
---
|
||
|
||
### Phase 6 - �®«ë© layout â ¡«¨æ (deferred)
|
||
|
||
‘¥©ç á (Phase 4-tables) â ¡«¨æë à¨áãîâáï "¤¥ª®à ⨢®" - ¯ ©¯ë ¨ â¨à¥
|
||
§ ¬¥ïîâáï box-drawing chars, ® è¨à¨ë ª®«®®ª ¡¥àãâáï ª ª ¥áâì ¨§
|
||
¨á室¨ª . –¥«ì Phase 6 - ¯¥à¥áç¨â âì â ¡«¨æã ¢ ®à¬ «¨§®¢ ë© ¢¨¤:
|
||
|
||
- **Pre-scan â ¡«¨æë**: ¯à®©â¨ ¢á¥ áâப¨ ®¤®£® table-¡«®ª , ©â¨
|
||
¬ ªá¨¬ «ìãî è¨à¨ã ª ¦¤®© ª®«®ª¨ (á ãçñ⮬ áꥤ¥ëå inline-¬ થ஢ -
|
||
¢¨§ã «ìë© à §¬¥à, ¥ ¡ ©â®¢ë©).
|
||
- **Re-emit ¢ ¡ãä¥à¥**: ¯à¨ § £à㧪¥ ä ©« (¨«¨ ¯à¨ ¯¥à¢®© ¢áâà¥ç¥ â ¡«¨æë)
|
||
¯¥à¥¯¨á âì áâப¨ ¢ FILE_BUF â ª, çâ®¡ë ¢á¥ ï祩ª¨ ®¤®© ª®«®ª¨ ¨¬¥«¨
|
||
®¤¨ ª®¢ãî è¨à¨ã; ¤®¡ ¢¨âì top/bottom à ¬ª¨ (`ÚÄÂÄ¿` / `ÀÄÁÄÙ`) ª ª
|
||
á¨â¥â¨ç¥áª¨¥ áâப¨. �â® ¯®§¢®«¨â á®åà ¨âì 1:1 ᮮ⢥âá⢨¥ "«®£¨ç¥áª ï
|
||
áâப > ®¤ viewport row" ¡¥§ á¯¥æ¨ «ì®© «®£¨ª¨ ¯à¨ ।¥à¥.
|
||
- **� ¬ïâì**: re-emit ¬®¦¥â “‚…‹ˆ—ˆ’œ ä ©« § áçñâ padding ¨ ¤®¯.à ¬®ª.
|
||
…᫨ ¡ãä¥à ¡«¨§®ª ª 16KB - ®â१ âì â ¡«¨æã ¨ ¯®¬¥â¨âì ¥ñ overflow'®¬.
|
||
- **ƒ®à¨§®â «ìë© áªà®««¨£**: ¥á«¨ ¨â®£®¢ ï è¨à¨ â ¡«¨æë (¨«¨ «î¡®©
|
||
áâப¨) > SCREEN_W = 80 - ¤®¡ ¢¨âì </> ¤«ï horizontal pan. �â® ¡ã¤¥â
|
||
®¡é¨© ¬¥å ¨§¬ ¤«ï ¤«¨ëå áâப (á¬. â ª¦¥ wrap mode), ¥ ⮫쪮 â ¡«¨æ.
|
||
- **‚ëà ¢¨¢ ¨¥ ¨§ separator-row**: `:-` > left, `-:` > right, `:-:` >
|
||
center; ãç¨âë¢ âì ¯à¨ padding'¥ ᮤ¥à¦¨¬®£® ï祩ª¨.
|
||
- **˜ £¨ ॠ«¨§ 樨**:
|
||
1. Walking pass ¯® ä¥á ¬/â ¡«¨æ ¬ ¯àאַ ¢ `index_lines()` - ᮡà âì
|
||
extents ¢á¥å â ¡«¨æ.
|
||
2. „«ï ª ¦¤®© â ¡«¨æë - ®¯à¥¤¥«¨âì è¨à¨ë ª®«®®ª.
|
||
3. �¥è¥¨¥: rewrite-in-buffer (¯à®é¥ ¤«ï ।¥à , ® ¬ãâ¨àã¥â ¨á室¨ª)
|
||
vs render-time layout (cleaner, ® âॡã¥â ®â¤¥«ì®© áâàãªâãàë
|
||
®¯¨á ¨ï layout' ª ¦¤ãî â ¡«¨æã).
|
||
4. Hpan: ®¡é¨© `viewport_x_offset` ¤«ï ¢á¥£® íªà , ¨«¨ ®â¤¥«ìë©
|
||
"è¨à®ª¨© ०¨¬" ⮫쪮 ¢ãâਠ⠡«¨æ.
|
||
|
||
> �¥ ¡«®ª¨àãîé ï ä¨ç . ‡ ¯ã᪠âì ª®£¤ á⠥⠯®ï⥠⨯®¢®© ¨áâ®ç¨ª
|
||
> markdown-ä ©«®¢ (㧪¨¥ ç¨â «ª¨ > ¤®áâ â®ç® ⥪ã饣® ¤¥ª®à â®à ;
|
||
> è¨à®ª¨¥ README á ¡®«ì訬¨ â ¡«¨æ ¬¨ > 㦥 ¯®«ë© layout).
|
||
|
||
---
|
||
|
||
### Phase ? - Šíè ।¥à¥ëå áâப (low priority)
|
||
|
||
Žâ«®¦¥®: ⥪ãé ï ᪮à®áâì ¡®«¥¥ 祬 ¤®áâ â®ç . €ªâ¨¢¨à®¢ âì ¥á«¨ ¯®ï¢¨âáï
|
||
áæ¥ ਩, £¤¥ ¢¨¤ § ¤¥à¦ª PgUp/PgDn ( ¯à¨¬¥à, ¯à¨ âï¦ñ«®¬ inline-¯ àá¥à¥
|
||
v2 á UTF-8 / linkifier / â ¡«¨æ ¬¨).
|
||
|
||
**Šíè ®âä®à¬ â¨à®¢ ëå áâப** (W3, ®â¤¥«ì ï EMM-áâà ¨æ ):
|
||
|
||
```
|
||
Cache layout (16 KB EMM page, ¢á¥£® 16000 ¡ ©â ¨á¯®«ì§ã¥âáï):
|
||
slot 0: 80 chars + 80 attrs = 160 bytes @ offset 0
|
||
...
|
||
slot 99: 80 chars + 80 attrs = 160 bytes @ offset 15840
|
||
|
||
Cache tags (W2 static): uint16_t cache_tag[100] = 200 bytes
|
||
cache_tag[i] = line_id, ¨«¨ 0xFFFF = invalid
|
||
```
|
||
|
||
‘âà ⥣¨ï - **direct map (no LRU)**: `slot = line_id % 100`. Š®««¨§¨ï > ¢ëâ¥á¥¨¥.
|
||
|
||
**Batched viewport render**: 2 page-swap' ‚…‘œ viewport (cache > file > cache),
|
||
¥ 60 ª ª ¯à¨ ¨¢®© ॠ«¨§ 樨.
|
||
|
||
�ਠᡮથ: `cache_blk = mem_alloc_pages(1)` ¯®á«¥ `file_blk`; `mem_free_block` exit.
|
||
|
||
---
|
||
|
||
## —â® ®â«®¦¥® ¢ v2
|
||
|
||
- ” ©«ë >16 KB: ¬®£®áâà ¨ç®¥ åà ¥¨¥ ç¥à¥§ `mem_alloc_pages(N)`, «¥¨¢ ï § £à㧪 áâà ¨æ ¢ W3 ¯à¨ ¤®áâ㯥.
|
||
- Search (Find / Find next) - F3 / F4.
|
||
- Toggle highlight on/off - F2.
|
||
- Word wrap.
|
||
- Image alt-text rendering.
|
||
- Tables.
|