# TInputLine  (guide pp. 460–464)

Rust module(s): `src/widgets/input_line.rs`   |   magiblot: `include/tvision/dialogs.h` / `source/tvision/tinputli.cpp`
Validator hook: `src/validate.rs`   |   Value protocol: `src/data.rs`

> The guide documents 7 public fields (CurPos, Data, FirstPos, MaxLen, SelEnd, SelStart, Validator),
> 11 methods (Init/Done, DataSize, Draw, GetData, GetPalette, HandleEvent, SelectAll, SetData, SetState,
> SetValidator, Store, Valid), and the palette CInputLine (4 entries).
> The magiblot C++ header also exposes MaxWidth, MaxChars, and the limitMode constructor parameter —
> magiblot extensions not in the 1992 Pascal guide but present in both C++ and Rust.

| Guide entry | Pg | Bucket | Corr | Rust symbol / mapping | Doc | Notes |
|---|---|---|---|---|---|---|
| `CurPos` (field) | 460 | PORTED | OK | `InputLine::cur_pos: i32` | 3 | Guide: "index to insertion point / current cursor position." Rust: byte offset, documented as such with the coordinate-model module note. Score 3: what + how/when (byte-offset caveat explained). |
| `Data` (field) | 461 | EQUIVALENT | OK | `InputLine::data: String` | 3 | Guide: `PString` pointer. Rust: owned `String` — idiomatic. Field doc explains UTF-8, direct-read vs. `set_value` guidance, and the no-raw-byte-arithmetic rule. Score 3. |
| `FirstPos` (field) | 461 | PORTED | OK | `InputLine::first_pos: i32` | 3 | Guide: "index to the first displayed character." Rust: explicitly documented as a *display column*, not a byte offset — the key extension over the C++ semantics. Score 3: what + how/when (column-vs-byte distinction). |
| `MaxLen` (field) | 461 | PORTED | OK | `InputLine::max_len: i32` | 3 | Guide: "maximum length allowed, excluding the length byte." Rust: byte cap, documented. Field doc explains byte semantics, how the value is derived from `limit` in `MaxBytes` mode, and cross-references `max_width`/`max_chars`. Score 3. |
| `MaxWidth` (field) | — | PORTED | OK | `InputLine::max_width: i32` | 3 | magiblot extension (not in 1992 guide). Field doc explains display-width semantics (terminal columns, CJK double-width), when it is active (`MaxWidth` mode), and the default unbounded value. Score 3. |
| `MaxChars` (field) | — | PORTED | OK | `InputLine::max_chars: i32` | 3 | magiblot extension (not in 1992 guide). Field doc explains grapheme-cluster semantics, when it is active (`MaxChars` mode), and the default unbounded value. Score 3. |
| `SelEnd` (field) | 461 | PORTED | OK | `InputLine::sel_end: i32` | 3 | Guide: "index to the end of the selection area." Rust: byte offset, documented. Score 3: what + byte-offset coordinate model noted. |
| `SelStart` (field) | 461 | PORTED | OK | `InputLine::sel_start: i32` | 3 | Guide: "index to the beginning of the selection area." Rust: byte offset, documented. Same as `sel_end`. |
| `Validator` (field) | 461 | EQUIVALENT | OK | `InputLine::validator: Option<Box<dyn Validator>>` | 3 | Guide: `PValidator` raw pointer, nil if none. Rust: `Option<Box<dyn Validator>>` — idiomatic. Field doc explains what a validator does (filter, check, transfer), when to read vs. use `set_validator`, and the ownership model. Score 3. |
| `Init` (constructor) | 461 | PORTED | OK | `InputLine::new(bounds, limit, validator, limit_mode)` + `InputLine::with_limit(bounds, limit)` | 3 | Guide: sets `sfCursorVis`, `ofSelectable + ofFirstClick`, allocates `MaxLen + 1` bytes. Rust: identical flags set, `String` replaces the heap buffer, `with_limit` is the simple convenience form. Docs explain all three limit modes and the flags. Score 3. |
| `Done` (destructor) | 462 | NOT-PORTED | — | — | — | Destructor frees `data` and `oldData` heap allocations and calls `destroy(validator)`. Rust: all fields are owned (`String`, `Option<Box<…>>`); Drop is automatic. No explicit `done`. |
| `DataSize` (method) | 462 | NOT-PORTED | — | — | — | Returns `MaxLen + 1` (or validator-computed size) for the untyped `getData`/`setData` record protocol. Rust replaces this entire untyped offset-arithmetic protocol with the typed D10 value protocol (`View::value` / `View::set_value`); `data_size` has no analog. Known idiomatic mapping: `getData`/`setData` → D10 value protocol. |
| `Draw` (method) | 462 | PORTED | OK | `InputLine::draw` (impl `View::draw`) | 3 | Guide: different colors for focused/unfocused, arrows when text exceeds width, selected text drawn with appropriate palette. Rust: faithful implementation; `Role::InputNormal` / `Role::InputArrow` / `Role::InputSelected` replace the raw palette indices (D7). Method doc names all three roles, explains the redraw-not-attr-only distinction, and notes the cursor-placement split. Score 3. |
| `GetData` (method) | 462 | EQUIVALENT | OK | `View::value` → `FieldValue::Text(data.clone())` or validator `transfer_get` | 3 | Guide: copies `DataSize` bytes from `Data^` into `Rec`; validator may intercept. Rust: `View::value()` returns `Option<FieldValue>`; the validator's `transfer_get` is tried first, then falls back to `FieldValue::Text`. Method doc explains both paths, the typed-transfer case (RangeValidator example), and how/when to call during gather. Score 3. |
| `GetPalette` (method) | 462 | EQUIVALENT | OK | `Role::InputNormal`, `Role::InputArrow`, `Role::InputSelected` + `tv::Theme` | 3 | Guide: returns `CInputLine` (4 entries: Passive, Active, Selected, Arrow — indices 19–21 of dialog palette). Rust: `Role`-keyed theme entries selected at draw time (D7). The `draw` method doc now names all three roles and explains their usage; no separate `get_palette` method exists in Rust (palette lookup is inlined at draw time). Score 3. |
| `HandleEvent` (method) | 463 | PORTED | OK | `InputLine::handle_event` (impl `View::handle_event`) | 3 | Guide: mouse (click/drag block mark, edge scroll, double-click select-all), keyboard (arrow/home/end/insert/delete/backspace/ctrl navigation, printable insert, Ctrl-G delete line), command (cut/copy/paste). Rust: faithful to `tinputli.cpp`; C++ mouse do-while loops become the async tracking-capture pattern (D3, documented); clipboard becomes `Deferred` (D8); keymap dispatched through `keymap::resolve_global`. Method doc now covers all three event categories (keyboard, mouse, command), press-and-hold capture, shift-extend, command graying, and the unhandled-key bubbling rule. Score 3. |
| `SelectAll` (method) | 463 | PORTED | OK | `InputLine::select_all(enable: bool, scroll: bool)` | 3 | Guide: sets `CurPos`, `FirstPos`, `SelStart` to 0; if `Enable` then `SelEnd = Length(Data^)`, else `SelEnd = 0`. Rust: identical logic. Method doc explains both args, when to pass `scroll=true` vs. `false`, the no-draw contract, and the command-graying follow-up. Score 3. |
| `SetData` (method) | 463 | EQUIVALENT | OK | `View::set_value(FieldValue)` | 3 | Guide: copies `DataSize` bytes from `Rec` into `Data^`, then calls `SelectAll(True)`. Rust: `set_value(FieldValue::Text(…))` loads text, truncates to `max_len`, calls `select_all(true, true)`; validator `transfer_set` handles typed values (D10). Method doc explains both paths, the truncation semantics, the type-mismatch drop rule, and the scatter-pass use case. Score 3. |
| `SetState` (method) | 463 | PORTED | OK | `InputLine::set_state` (impl `View::set_state`) | 3 | Guide: calls `TView.SetState`; if `AState` is `sfSelected` or (`sfActive` and field is `sfSelected`), calls `SelectAll(Enable)`. Rust: faithful. Method doc explains both effects: the `select_all` trigger on focus change and the command-graying push when the active+selected condition changes. Score 3. |
| `SetValidator` (method) | 463 | EQUIVALENT | OK | `InputLine::set_validator(&mut self, validator: Option<Box<dyn Validator>>)` | 3 | Guide: disposes existing validator, assigns new one. Rust: `set_validator` method exists and is fully documented (what it does, when to use it vs. constructor, drop semantics, heritage note). Score 3. |
| `Store` / `Load` (streaming) | 463 | NOT-PORTED | — | — | — | Pascal streaming machinery. Rust drops `TStreamable` (deviation D12). |
| `Valid` (method) | 464 | PORTED | OK | `InputLine::valid(cmd: Command, ctx: &mut Context) -> bool` | 3 | Guide: with validator — `cmValid` checks `validator.status == vsOk`; `cmCancel` passes unconditionally; any other command calls `validator.validate(Data^)`, on fail calls `Select()` and returns False. Rust: faithful. `validator.status == vsOk` → `validator.is_status_ok()`. `Select()` (re-focus) → `ctx.request_focus(id)` via Deferred (D3, documented in inline comment). Score 3: what, how, when — including the three command-class branches. |
| `CInputLine` palette (4 entries) | 464 | EQUIVALENT | OK | `Role::InputNormal`, `Role::InputArrow`, `Role::InputSelected` (Theme) | 3 | Guide: `CInputLine` maps indices 1–4 to dialog palette entries 19–21 (Passive, Active, Selected, Arrow). Entries 1 and 2 both map to 19 (passive == active in this palette). Rust uses three named `Role` enum variants keyed at draw time; the `draw` method doc now explains all three roles and the redraw-not-attr-only distinction. The Role variants themselves live in `theme.rs` (deferred to theme.rs Role pass). Score 3. |
| `check_valid` auto-fill clamp (internal) | — | PORTED | OK | `InputLine::check_valid` lines 334–365 | N/A | The comment at line 334 ("a future mutating validator that SHRINKS data could leave cur_pos past end-of-string") is a deliberate TODO, not a deferred feature. No bundled validator shrinks. The auto-fill clamp path (`curPos >= oldLen && newLen > oldLen → curPos = newLen`) faithfully replicates `tinputli.cpp:289–291`. Classified OK — the comment documents a known limitation, not a missing behaviour. |

## Summary

- PORTED: 14   EQUIVALENT: 7   NOT-PORTED: 3   MISSING: 0   UNSURE: 0
- SUSPECT: 0   |   doc<3 (public): 0   |   → concept: 0
- Notable findings: All previously below-bar public symbols raised to score 3. `set_validator` is a live method (not constructor-only); its doc is score 3. `Role::Input*` variants documented in `src/theme.rs` in the theme.rs Role pass: `InputNormal` (white on blue, chain), `InputSelected` (white on green, chain), `InputArrow` (lightgreen on blue, chain).
