# TView  (guide pp. 560–576)

Rust module(s): src/view/view.rs, src/view/mod.rs, src/view/context.rs, src/view/geometry.rs, src/view/group.rs, src/data.rs, src/app/program.rs   |   magiblot: include/tvision/views.h / source/tvision/tview.cpp

> TView is the keystone abstract base. Deviation D2 splits it: its **data members**
> become the composed [`ViewState`] struct; its **virtual methods** become the
> [`View`] trait. The packed `sf*`/`of*`/`gf*`/`dm*` flag words become
> structs-of-bools (D5). Owner/sibling/peer pointers become `ViewId` handles + a
> downward [`Context`] (D3); the streaming family (`Load`/`Store`/`GetPeerViewPtr`/
> `PutPeerViewPtr`) is dropped (D-stream). Up-tree operations (focus/select/sibling
> nav/coordinate transforms) live on [`Group`] because a view has no up-pointer.

## Fields (guide pp. 561–563)

| Guide entry | Pg | Bucket | Corr | Rust symbol / mapping | Doc | Notes |
|---|---|---|---|---|---|---|
| `Cursor` (field) | 561 | PORTED | OK | `ViewState.cursor: Point` | 3 | View-local hardware-cursor position; visible only when focused+`cursor_vis`. Matches C++. Doc explains what and when. |
| `DragMode` (field) | 561 | EQUIVALENT | OK | `ViewState.drag_mode: DragMode` (struct-of-bools) | 3 | The packed `dm*` byte → struct-of-bools (D5). Each field names its `dm*` source; `limit_all()` = `dmLimitAll`. Note Rust adds `drag_grow_left` (`dmDragGrowLeft`, a magiblot extension) — present in magiblot's source, so faithful. |
| `EventMask` (field) | 561 | EQUIVALENT | OK | `ViewState.event_mask: EventMask` | 3 | **Documented deviation:** the three always-on classes (`evMouseDown`/`evKeyDown`/`evCommand`) are unconditional in tvision-rs rather than opt-in bits, so only the mouse-move/auto opt-ins survive in the mask. Field doc + ctor doc both call this out. C++ default `evMouseDown|evKeyDown|evCommand` is the "always-on" baseline; equivalent. |
| `GrowMode` (field) | 561 | EQUIVALENT | OK | `ViewState.grow_mode: GrowMode` (struct-of-bools) | 3 | Packed `gf*` byte → struct-of-bools (D5); `grow_all()` = `gfGrowAll`. `rel`=`gfGrowRel`, `fixed`=`gfFixed`. Matches. |
| `HelpCtx` (field) | 562 | PORTED | OK | `ViewState.help_ctx: HelpCtx` | 3 | Help context; `get_help_ctx()` returns `DRAGGING` while dragging else the field, faithful to C++ `getHelpCtx`. The "defaults to owner's context when `hcNoContext`" fallback is realized in the status-line switch (group aggregates), not on the bare field. Doc now explains when/how to set it. |
| `Next` (field) | 562 | EQUIVALENT | OK | `Group.children` Z-order vec + `Group::find_next(forwards)` (`src/view/group.rs:561`) | N/A | The circular `Next` sibling pointer → the owning group's child vec (D3); a view holds no sibling pointer. Sibling nav is `Group::find_next(forwards) -> Option<ViewId>` (and `focus_next(forwards, ctx)` for focus moves). Private/internal. |
| `Options` (field) | 562 | EQUIVALENT | OK | `ViewState.options: Options` (struct-of-bools) | 3 | Packed `of*` word → struct-of-bools (D5); `centered()` = `ofCentered`. **Documented drop:** `ofBuffered` (per-view back buffer — whole-tree redraw makes it moot) and the `ofVersion*` streaming bits. Faithful. |
| `Origin` (field) | 562 | PORTED | OK | `ViewState.origin: Point` | 3 | Owner-relative top-left. Matches. Doc now explains when to read it and how to write it (via set_bounds/move_to). |
| `Owner` (field) | 563 | EQUIVALENT | OK | `ViewState.id: Option<ViewId>` + downward `Context` (D3) | N/A | The up-pointer to the owning `TGroup` is removed entirely (D3): a view knows only its own `ViewId`; owner data (size/phase) arrives downward via `Context`. `id` is `pub(crate)` write-once, stamped by `Group::insert`. The field doc explicitly states it is NOT an up-pointer. `pub(crate)` — not held to the public bar. |
| `Size` (field) | 563 | PORTED | OK | `ViewState.size: Point` | 3 | View size. Matches. Doc now explains how to use it (read via get_bounds/get_extent; set via set_bounds/grow_to). |
| `State` (field) | 563 | EQUIVALENT | OK | `ViewState.state: State` (struct-of-bools) | 3 | Packed `sf*` word → struct-of-bools (D5). **Documented drop:** `sfExposed` (occlusion cache — replaced by whole-tree redraw+diff). Each field names its `sf*` source. Faithful. |

## Methods (guide pp. 563–576)

| Guide entry | Pg | Bucket | Corr | Rust symbol / mapping | Doc | Notes |
|---|---|---|---|---|---|---|
| `Init` (constructor) | 563 | PORTED | OK | `ViewState::new(bounds: Rect) -> ViewState` | 3 | C++ defaults: `state=sfVisible`, `dragMode=dmLimitLoY`, `eventMask=evMouseDown\|evKeyDown\|evCommand`, `helpCtx=hcNoContext`, growMode=0, options=0, cursor=(0,0). Rust `new` sets visible + `limit_lo_y` + `NO_CONTEXT`; eventMask all-false (the three classes are unconditional, documented). Verified against `tview.cpp` ctor. The "always call inherited Init first" + zero-init is replaced by explicit field init (no inheritance). |
| `Load` (constructor) | 563 | NOT-PORTED | — | — | — | Stream deserialization. `TStreamable` family dropped (D-stream; serde-if-revived). Module doc: "serialization is gone". |
| `Done` (destructor) | 564 | EQUIVALENT | OK | `Drop` + `Group` child removal / `remove_descendant` | N/A | C++ `Done` hides then removes from owner. tvision-rs: the loop's child-removal (`Deferred::Close` → `remove_descendant`) plus Rust `Drop` for memory. Module doc: "teardown collapses into the one loop plus `Drop`". |
| `Awaken` (method) | 564 | PORTED | OK | `View::awaken` (default no-op) | 3 | Post-load init hook. Base no-op, faithful. Doc now explains when to override (tree-wired initialization, resolving sibling ids). |
| `BlockCursor` (method) | 564 | PORTED | OK | `ViewState::block_cursor` | 3 | Sets `cursor_ins` (block shape). Matches; doc explains pairing with show_cursor and normal_cursor for toggle. |
| `CalcBounds` (method) | 564 | PORTED | OK | `View::calc_bounds` + `ViewState::calc_bounds` | 3 | Computes new bounds from grow mode on owner resize. Rust splits: the trait method computes size-limits via the overridable `size_limits` hook then delegates the grow math to `ViewState::calc_bounds` (the single source). `grow`/`fit_to_limits`/`balanced_range`/`range` port the `tview.cpp` statics; `resize_balance` accumulator ported. Returns bounds (does not apply) — `change_bounds` applies. Verified math via unit tests. |
| `ChangeBounds` (method) | 564 | PORTED | OK | `View::change_bounds` | 3 | C++ `setBounds(bounds); drawView()`. Rust base sets bounds; the redraw is automatic under whole-tree redraw (documented). Groups/windows override to propagate to children. Doc now explains when to call vs when to use Context::request_bounds. |
| `ClearEvent` (method) | 565 | EQUIVALENT | OK | `Event::clear` / `ev.is_nothing()` + handlers set `Event::Nothing` | N/A | C++ sets `What=evNothing`, `InfoPtr=@Self`. tvision-rs handlers mark the event handled by setting it to `Event::Nothing` (the `is_nothing()` check drives consumption in routing). The `InfoPtr=@Self` carrier is dropped (D4: broadcasts carry a resolvable `ViewId` subject, not a value). Idiomatic. |
| `CommandEnabled` (method) | 565 | EQUIVALENT | OK | `Context::command_enabled(cmd) -> bool` | 3 | Reads the per-pump disabled-set snapshot (denylist: enabled iff not disabled). A view holds no `&Program`, so this answers from an owned snapshot (documented aliasing rationale). Matches C++ semantics. |
| `DataSize` (method) | 565 | EQUIVALENT | OK | D10 value protocol — `FieldValue` typed currency (`src/data.rs`) | N/A | C++ `DataSize`/`GetData`/`SetData` are the untyped byte-record transfer. tvision-rs replaces the whole family with the **typed** `View::value`/`set_value` (`FieldValue`) — a known idiomatic mapping (D10). `DataSize` (the byte count) has no analog because the typed protocol needs none. |
| `DisableCommands` (method) | 565 | EQUIVALENT | OK | `Context::disable_command(cmd)` (deferred) | 3 | C++ takes a `TCommandSet`; tvision-rs disables one command per call, deferred via `Deferred::DisableCommand` (a view has no `&Program`). Multiple calls for a set. The denylist model (A1) is documented. Doc now explains when to call, deferred semantics, and how to re-enable. |
| `DragView` (method) | 565 | EQUIVALENT | OK | `MouseTrackCapture` / window drag-resize capture handler + `Context::request_bounds` | 3 | C++ `DragView` runs a blocking drag loop clamping to `Limits`/`Min`/`Max` by `dm*` mode. tvision-rs replaces the blocking loop with a capture handler (the modal mouse hold → `start_mouse_track`), and the window frame drives move/grow, requesting bounds via `Deferred::ChangeBounds`. The limits are captured at push time (owner_size valid then). Documented seam (`docs/design/mouse-track.md`). |
| `Draw` (method) | 566 | PORTED | OK | `View::draw(&mut self, ctx: &mut DrawCtx)` (required) | 3 | Must cover the whole view; required (no default — a bare view has no palette). Replaces the C++ `Draw`. The `GetClipRect`-driven partial redraw optimization is folded into `DrawCtx`'s clip (passed down). |
| `DrawView` (method) | 566 | EQUIVALENT | OK | whole-tree redraw + diff (loop) | N/A → concept | C++ `DrawView` = "draw only if `Exposed`". tvision-rs drops per-view exposure: the loop redraws the whole tree each pump and diffs against the prior buffer (D11/D-redraw). No `draw_view` method — `draw` is called unconditionally by the painter, occlusion handled by paint order + diff. → concept (the view-tree / redraw model lives in the mdBook). |
| `EnableCommands` (method) | 566 | EQUIVALENT | OK | `Context::enable_command(cmd)` (deferred) | 3 | Mirror of `DisableCommands`. Per-command, deferred. Doc now explains when to call, deferred semantics, and denylist model. |
| `EndModal` (method) | 566 | EQUIVALENT | OK | `Context::end_modal(cmd)` (view, deferred) / `Program::end_modal(cmd)` (owner) | 3 | Two paths: a view holds only `&mut Context` → `ctx.end_modal` (deferred `EndModal`, sets `Program::end_state`); the owner/top-level path is the immediate `Program::end_modal`. Documented rule of thumb. Faithful to terminating the modal with a command. |
| `EventAvail` (method) | 566 | EQUIVALENT | OK | folded into the single event loop (`pump_once`) | N/A | C++ `EventAvail` = "is a GetEvent ready". The blocking pump model (D9) replaces poll-then-handle: there is no separate `event_avail` query; the loop pumps events. Module doc: "the blocking event-pump … collapse into the one loop". |
| `Execute` (method) | 566 | EQUIVALENT | OK | `Program::exec_view` runs the modal loop; views don't override `Execute` | N/A | C++ `Execute` is the per-view modal event loop, overridden by modal views. tvision-rs has a single loop (D9): modality is `Program::exec_view` + `end_state`, not a per-view `Execute` override. The default `TView.Execute` returning `cmCancel` is moot. |
| `Exposed` (method) | 567 | NOT-PORTED | — | — | — | "Is any part visible on screen". Occlusion/exposure tracking (`sfExposed`) is dropped under whole-tree redraw + diff (D-redraw). No analog — the painter paints all visible views and the diff suppresses unchanged cells. Documented in module doc + `State` doc. |
| `Focus` (method) | 567 | EQUIVALENT | OK | `Group::focus_child` / `Group::focus_next` (up-tree, on Group) | 3 | C++ `Focus` can *fail* (a sibling may refuse to release focus). tvision-rs focus drive lives on `Group` (a view has no up-pointer): `focus_child`/`focus_next`/`set_current` apply the selectable gate and run the validation/release. EQUIVALENT (moved to Group, D3). |
| `GetBounds` (method) | 567 | PORTED | OK | `ViewState::get_bounds() -> Rect` | 3 | `{origin, origin+size}`. Matches exactly. Doc now explains when to use vs get_extent. |
| `GetClipRect` (method) | 567 | EQUIVALENT | OK | `DrawCtx::clip() -> Rect` | 3 | C++ returns the minimum rect needing redraw. tvision-rs passes the clip down on `DrawCtx` (already intersected with the buffer); a view reads `ctx.clip()`. Doc now explains it's an optimization (write methods already clip) and that coordinates are absolute. |
| `GetColor` (method) | 567 | EQUIVALENT | OK | `DrawCtx::style(role: Role) -> Style` + `tv::Theme` | 3 | C++ `GetColor` maps a palette index up the owner-palette chain to a physical attribute. tvision-rs: a view asks `ctx.style(Role::…)` directly against the active `Theme` (D7: class Palette → Theme; known idiomatic mapping). No index-chain walk — roles resolve in the theme. Doc now explains how/when to use it in draw. |
| `GetCommands` (method) | 567 | EQUIVALENT | OK | `Context::command_enabled` (read) / `Program` owns the set | N/A | C++ copies the current `TCommandSet`. tvision-rs keeps the command set on `Program` (denylist); a view does not get a whole-set copy — it queries per-command via `command_enabled`. EQUIVALENT (no whole-set view accessor; not needed). |
| `GetData` (method) | 568 | EQUIVALENT | OK | `View::value() -> Option<FieldValue>` + `Group::gather_data` | 3 | D10 value protocol: typed `value()` replaces the byte-copy `GetData`; dialog gather is `Group::gather_data`. Doc now explains the gather walk, how to override, and how to ignore a non-understood variant. |
| `GetEvent` (method) | 568 | EQUIVALENT | OK | the loop's `pump_once` (`Program`/`Application`) | N/A | C++ `GetEvent` (default: call owner's). tvision-rs has a single loop that pulls from the backend + the `out_events` queue (D9); no per-view `get_event`. Idiomatic. |
| `GetExtent` (method) | 568 | PORTED | OK | `ViewState::get_extent() -> Rect` | 3 | `{0,0,size.x,size.y}`. Matches exactly. Doc now explains use inside draw for layout/fill. |
| `GetHelpCtx` (method) | 568 | PORTED | OK | `View::get_help_ctx` / `ViewState::get_help_ctx` | 3 | Returns `DRAGGING` while dragging else `help_ctx`. Matches C++. Group overrides to aggregate the focused child's context. Doc now explains callers (status line), when to override, and drag-override behavior. |
| `GetPalette` (method) | 568 | EQUIVALENT | OK | `tv::Theme` role lookups (no per-view `PPalette`) | N/A | C++ `GetPalette` returns the view's palette string (almost always overridden). tvision-rs drops the palette-string-up-the-chain mechanism for direct `Role`→`Theme` lookups (D7). No `get_palette` on the trait — widgets pick roles at draw time. EQUIVALENT (known idiomatic mapping). |
| `GetPeerViewPtr` (method) | 568 | NOT-PORTED | — | — | — | Reads a peer-view pointer from a stream during `Load`. Streaming-only (`TStreamable`) — dropped (D-stream). The live cross-view sibling access it enabled is replaced by the `ViewId` deferred-broker (D3), not this. |
| `GetState` (method) | 569 | PORTED | OK | `ViewState.state.<flag>` direct field reads | N/A | C++ `GetState(aState)` tests a bit. tvision-rs reads the bool field directly (`self.state().state.focused`). EQUIVALENT-by-directness; the bit-test wrapper is unnecessary with struct-of-bools. No distinct method exists — direct field access is idiomatic Rust. |
| `GrowTo` (method) | 569 | PORTED | OK | `ViewState::grow_to(x, y)` | 3 | Keeps origin, sets size. C++ `GrowTo` calls `Locate`; the owner-dependent size clamp moves to `locate` (free fn) / Group, documented. Doc now explains the plain-field-flip nature and when to use vs change_bounds. |
| `HandleEvent` (method) | 569 | PORTED | OK | `View::handle_event(&mut Event, &mut Context)` (default no-op) | 3 | C++ `HandleEvent`'s base auto-selects a selectable view on `evMouseDown`. tvision-rs base is a **no-op**; the auto-select lives on `Group::route_event` (drives focus top-down) gated by `grabs_focus_on_click` — documented deviation. The central event entry point. |
| `Hide` (method) | 569 | PORTED | OK | `ViewState::hide` | 3 | Clears `visible`. The repaint/reset-current side effects are dropped (loop repaints; group owns currency) — documented. Doc now explains plain-field-flip vs Context::request_set_visible for live-tree visibility. |
| `HideCursor` (method) | 569 | PORTED | OK | `ViewState::hide_cursor` | 3 | Clears `cursor_vis`. Matches. Doc now explains use for software-drawn cursors to suppress the hardware cursor. |
| `KeyEvent` (method) | 570 | EQUIVALENT | OK | folded into the single event loop (blocking key wait) | N/A | C++ `KeyEvent` blocks until the next `evKeyDown`. tvision-rs's modal hold/loop reads events off the queue (D9); no per-view blocking `key_event` helper. Subsumed by the loop. |
| `Locate` (method) | 570 | PORTED | OK | `view::locate(view, bounds, owner_size)` (free fn) | 3 | C++ `Locate`: `SizeLimits`-clamp, then `ChangeBounds`. Rust ports it as a **free function** (not a trait method) deliberately — so `size_limits` dispatches virtually to a wrapper's override (window min) instead of the macro forwarding it to the inner 0×0 group. Documented hazard + rationale. Backs desktop tile/cascade. |
| `MakeFirst` (method) | 570 | EQUIVALENT | OK | `Group::make_first(id, ctx)` | 3 | Documented on Group (score 3 verified): doc says "Move child `id` to the top (frontmost) of the Z-order", calls `put_in_front_of(id, None, ctx)`, heritage names `TView::makeFirst`. On Group (up-tree op, D3). Matches. |
| `MakeGlobal` (method) | 570 | EQUIVALENT | OK | origin accumulation in routing / `Group::descendant_global_bounds` | N/A | Local→global transform. No standalone `make_global` method: the group accumulates child origins on each delivery and `descendant_global_bounds` walks origins for the absolute frame. Folded into routing (D3). EQUIVALENT. |
| `MakeLocal` (method) | 570 | EQUIVALENT | OK | per-delivery origin subtraction in `Group::route_event` (`mouse_pos_mut(&mut local) -= origin`) | N/A | Global→local transform. Routing localizes a mouse event by subtracting the child's origin at each level (group.rs ~768); no view-facing `make_local`. Folded into routing (D3). EQUIVALENT. |
| `MouseEvent` (method) | 570 | EQUIVALENT | OK | `MouseTrackCapture` / `Context::start_mouse_track` (modal hold) | 3 | C++ `MouseEvent` tracks the mouse while a button is held (block-marking loop), returning on `evMouseUp`. tvision-rs replaces the blocking `do…while(mouseEvent())` with the mouse-track capture (`start_mouse_track` → `Deferred::MouseTrack` per masked move/up). Documented as the direct port of `tview.cpp:636-643`. EQUIVALENT. |
| `MouseInView` (method) | 570 | EQUIVALENT | OK | hit-test in routing (`Rect::contains` against group-local bounds) | N/A | C++ `MouseInView(global pt)`. tvision-rs hit-tests the positional event against the child's bounds during routing (`mouse_pos_mut` + bounds `contains`), not via a view-facing method. `Rect::contains` is the half-open test. Folded into routing. EQUIVALENT. |
| `MoveTo` (method) | 571 | PORTED | OK | `ViewState::move_to(x, y)` | 3 | Sets origin, keeps size. Matches; size-limit clamp on the group, documented. Doc now explains plain-field nature and when to use vs change_bounds. |
| `NextView` (method) | 571 | EQUIVALENT | OK | `Group::find_next(true)` (`src/view/group.rs:561`) | N/A | C++ returns the next subview, `nil` at the last. Rust: `find_next(forwards) -> Option<ViewId>` on Group (D3). EQUIVALENT. |
| `NormalCursor` (method) | 571 | PORTED | OK | `ViewState::normal_cursor` | 3 | Clears `cursor_ins` (underline shape). Matches. Doc now explains use after block_cursor on insert-mode toggle. |
| `Prev` (method) | 571 | EQUIVALENT | OK | `Group` sibling walk (circular) | N/A | C++ `Prev` treats the list as circular (wraps to last). On Group (D3). EQUIVALENT. |
| `PrevView` (method) | 572 | EQUIVALENT | OK | `Group` sibling walk (linear, `nil` at first) | N/A | Linear variant of `Prev`. On Group (D3). EQUIVALENT. |
| `PutEvent` (method) | 572 | EQUIVALENT | OK | `Context::put_event(ev)` / `Context::post(cmd)` | 3 | C++ `PutEvent` pushes the next event (default: owner's). tvision-rs: `ctx.put_event` (raw) / `ctx.post` (command) push into the loop's `out_events`, drained before the backend poll. Doc now explains when to use vs post/broadcast and that it processes on the next pump cycle. |
| `PutInFrontOf` (method) | 572 | EQUIVALENT | OK | `Group::put_in_front_of(id, target, ctx)` | 3 | Documented on Group (score 3 verified): doc explains Z-order "in front of target", guards (no-op for same/already-in-place), no send-to-bottom, and currency reset on selectable move. Heritage names `TView::putInFrontOf`. On Group (D3). Matches semantics. |
| `PutPeerViewPtr` (method) | 572 | NOT-PORTED | — | — | — | Writes a peer-view pointer to a stream during `Store`. Streaming-only — dropped (D-stream). |
| `Select` (method) | 573 | EQUIVALENT | OK | `Group::set_current` / `focus_child` (SelectMode) | 3 | Documented on Group (score 3 verified): `set_current` doc explains unvalidated path, all three `SelectMode` variants (Normal/Enter/Leave) with side effects, focused-flag propagation, and `SelectNext` composition pattern. Heritage names `TGroup::setCurrent`. C++ `Select` sets `sfSelected` (and `sfFocused` if owner focused; `MakeFirst` if `ofTopSelect`). tvision-rs drives selection from the owning group (D3). EQUIVALENT. |
| `SetBounds` (method) | 573 | PORTED | OK | `ViewState::set_bounds(bounds)` | 3 | `origin=a; size=b-a`. Matches. C++ warns "call only from ChangeBounds" — same intent (it is `pub` but the resize path goes through change_bounds). Doc now explains its role as a low-level primitive. |
| `SetCmdState` (method) | 573 | EQUIVALENT | OK | `Context::enable_command`/`disable_command` (per Enable flag) | N/A | C++ `SetCmdState(set, enable)` = shortcut for Enable/DisableCommands. tvision-rs: call the matching per-command method by the bool. EQUIVALENT (no single combined call, not needed). |
| `SetCommands` (method) | 573 | EQUIVALENT | OK | `Program` owns the command set (denylist); no whole-set replace from a view | N/A | C++ `SetCommands` replaces the whole current set. tvision-rs models the set as a `Program`-owned denylist mutated per-command (A1, documented); there is no view-facing whole-set replace. EQUIVALENT. |
| `SetCursor` (method) | 573 | PORTED | OK | `ViewState::set_cursor(x, y)` | 3 | Sets view-local cursor; the absolute hardware placement is the loop's job (needs the tree), documented. Doc now explains when to call and the show_cursor pairing. |
| `SetData` (method) | 573 | EQUIVALENT | OK | `View::set_value(FieldValue)` + `Group::scatter_data` | 3 | D10 value protocol (typed) replaces the byte-copy `SetData`; dialog scatter is `Group::scatter_data`. Doc now explains how to override, scatter walk, and ignoring unknown variants. |
| `SetState` (method) | 573 | PORTED | OK | `View::set_state(flag: StateFlag, enable, ctx)` | 3 | C++ `SetState(aState, enable)` flips a bit + side effects (redraw exposed on visibility change, reprogram cursor, enable/disable commands). tvision-rs restricts the propagating hook to the four focus/activation flags (`StateFlag`), emits the focus broadcast (`RECEIVED/RELEASED_FOCUS`) for `Focused`; visibility/cursor flips go directly on `ViewState` (their side effects are dropped under whole-tree redraw). The "always call inherited first" guidance maps to Group overriding + calling through. Documented split. |
| `Show` (method) | 574 | PORTED | OK | `ViewState::show` | 3 | Sets `visible`. Side effects (repaint, reset-current) dropped, documented. Doc now explains plain-field-flip vs Context::request_set_visible for live-tree visibility. |
| `ShowCursor` (method) | 574 | PORTED | OK | `ViewState::show_cursor` | 3 | Sets `cursor_vis`. Matches. Doc now explains pairing with set_cursor and block/normal_cursor. |
| `SizeLimits` (method) | 574 | PORTED | OK | `View::size_limits` / `ViewState::size_limits` | 3 | C++ default: `min=(0,0)`, `max=Owner^.Size`. Rust default identical, except `fixed` (`gfFixed`) → `max=(i32::MAX, i32::MAX)` (a magiblot-faithful extension). Overridable (windows impose a minimum). Verified via tests. (Raised to score 3 — trait method doc explains override and gfFixed.) |
| `Store` (method) | 575 | NOT-PORTED | — | — | — | Stream serialization. `TStreamable` dropped (D-stream). |
| `TopView` (method) | 575 | EQUIVALENT | OK | `Program` modal stack / `exec_view` | N/A | C++ `TopView` returns the current modal view. tvision-rs tracks modality through `Program::exec_view` (the modal it is currently running); no free `top_view` accessor on a view. EQUIVALENT (loop-owned, D9). |
| `Valid` (method) | 575 | PORTED | OK | `View::valid(cmd: Command, ctx: &mut Context) -> bool` | 3 | C++ `Valid(command)`: `cmValid` checks construction; nonzero checks a modal-end; `ofValidate` triggers `cmReleaseFocus`. tvision-rs base returns `true`; **carries `&mut Context`** (a deviation/extension) so validation can request an async modal message box (`request_message_box`) and re-validate via `set_modal_answer` — documented seam (`docs/design/async-modal-from-view.md`). `Command::RELEASED_FOCUS` maps `cmReleaseFocus`. Faithful + extended. |
| `WriteBuf` (method) | 575 | EQUIVALENT | OK | `DrawCtx::fill` / buffer writes via `DrawCtx` | N/A | C++ `WriteBuf(x,y,w,h,buf)` blits a `TDrawBuffer`. tvision-rs replaces `TDrawBuffer`+owner-relative math with `DrawCtx` view-local writes (`fill`/`put_*`) over the vendored cell buffer (D11). No raw buf blit; `DrawCtx` is the successor (documented). EQUIVALENT. |
| `WriteChar` (method) | 576 | EQUIVALENT | OK | `DrawCtx::put_char(x, y, ch, style)` | 3 | C++ `WriteChar(x,y,ch,color,count)` writes `count` copies at a palette color. tvision-rs `put_char` writes one cell at a `Style` (role-resolved); width-aware + clipped. The `count` repeat maps to a caller loop / `fill`. Palette index → `Style` (D7). EQUIVALENT. |
| `WriteLine` (method) | 576 | EQUIVALENT | OK | `DrawCtx::put_str` / `put_str_part` / `put_cstr` | 3 | C++ `WriteLine(x,y,w,h,buf)` writes a buffered line, repeated `h` times. tvision-rs writes strings view-local + clipped (`put_str`, `put_cstr` for the `~` hotkey toggle); the `h`-repeat maps to a caller loop. Successor to `move_str_part`/`move_cstr_part`. EQUIVALENT. |
| `WriteStr` (method) | 576 | EQUIVALENT | OK | `DrawCtx::put_str(x, y, s, style)` | 3 | C++ `WriteStr(x,y,str,color)` writes a string at a palette color. tvision-rs `put_str` writes view-local with a role-resolved `Style`, returning columns written. Palette → Style (D7). EQUIVALENT. |

## Palette (no own palette)

> TView is abstract and has **no palette entry of its own** (the guide documents
> none on pp. 560–576 — `GetPalette` returns `nil` by default). Concrete views
> supply theirs via the `tv::Theme` role mapping (D7). No row.

## Summary

- PORTED: 28   EQUIVALENT: 45   NOT-PORTED: 5   MISSING: 0   UNSURE: 0
- SUSPECT: 0   |   doc<3 (public): 0   |   → concept: 1 (`DrawView` → view-tree/redraw model)
- Reconciliation: `MakeFirst` → `Group::make_first` verified score-3; `PutInFrontOf` → `Group::put_in_front_of` verified score-3; `Select` → `Group::set_current` verified score-3. All three re-scored to 3.
- N/A added: `Owner`/`id` (`pub(crate)`); `GetState` (no distinct method — direct field access); remaining N/A rows unchanged.
- Notable findings: **No gaps and no suspect items** — every TView field/method has a faithful counterpart or a documented, deliberate deviation. The five NOT-PORTED entries are all the streaming family (`Load`/`Store`/`GetPeerViewPtr`/`PutPeerViewPtr`) plus `Exposed` — dropped under the documented `TStreamable`-removed (D-stream) and whole-tree-redraw (D-redraw) decisions. The large EQUIVALENT count reflects the three structural deviations that define the whole port: D2 (data→`ViewState` / methods→`View` trait), D3 (owner/sibling/peer pointers → `ViewId` + downward `Context`, so focus/select/sibling-nav/coordinate-transforms move to `Group`), and D5/D7 (flag words → struct-of-bools, palette → `Theme`). All are pre-decided and individually documented. The one detail worth a reader's note: `View::valid` carries `&mut Context` (an extension beyond C++ `Valid(command)`) to support the async-modal-from-a-view seam — clearly documented, not a divergence.
