# tvision-m2 - milestone summary (2026-09-16) A TVision/Turbo-Vision style character-cell UI toolkit written in ISO GNU Modula-2 (`gm2 -fiso`) for the terminal, developed alongside the tigr and microui bindings in this repository. No C source and no graphics dependency; the only non-Modula-2 part is the libc binding `tvtty.def`. ## Status Working milestone: a retained view tree with clipping and z-order, a diffed ANSI screen, keyboard + mouse input, widgets and modal dialogs. Builds warning-free and was exercised by driving a real pty (frames reconstructed from the captured terminal stream). ## Files | file | role | |---|---| | `tvtty.def` | libc binding: raw mode, winsize, read/write | | `tv.def` / `tv.mod` | screen, view tree, widgets, events, modal dialog | | `demo.mod` | demo application (two windows, all widgets, mouse) | | `ttysize.mod` | diagnostic for the tty binding | | `Makefile` | build | | `README.md` | build/run + API + GM2 notes | ## Implemented - Alternate screen, hidden/show cursor, terminal restore on exit. - 16-colour fg/bg, explicit blink on/off, UTF-8 box drawing, clipping stack. - Diffed redraw: only changed cells are written. - View tree: groups and windows own children; per-window clipping; z-order with click-to-front; windows draggable by the title row (any direction), resizable by the bottom-right handle (`WindowResize`), clamped so the title stays on screen; ` X ` close box. - Widgets: static text, frame, input line (insert/backspace/delete/Home/End/ arrows), push button, check box, radio buttons, list box (selection, wheel scroll) and vertical scroll bar. - Focus chain (Tab / Shift-Tab / up-down); hardware cursor in the focused input; Enter/Space activate. - Keyboard decoding: printable UTF-8, arrows, Home/End, PgUp/PgDn, Ins/Del, F1-F12, Enter, Space, Backspace, Esc, Ctrl-C. - Mouse: xterm SGR reporting (mode 1002/1006) - click to focus/press, drag titles, click list rows, wheel scroll. - Generic modal dialog builder (`Dialog`/`Dlg*`/`DlgRun`) with inputs, check boxes (self-exclusive radio groups) and tagged buttons; `MessageBox` (OK / OK-Cancel / Yes-No) and the `Message` shorthand. - SIGWINCH-driven resize detection via a libc `signal` handler. - Multi-line editor widget (`VEditor`) with insert/overwrite, navigation, Tab indent, mouse positioning, a Ln/Col/Insert/Modified status row and file load/save; syntax highlighting for Modula-2/Pascal/Oberon and automatic keyword up-casing and auto-indentation for Modula-2/Oberon (indent after open keywords, dedent on close keywords); demo `examples/edit` (with a Syntax menu to switch language). - Example programs (`empty`, `window`, `dialog`, `menus`, `edit`, `gfx`); API reference (`API.md`) and tutorial (`TUTORIAL.md`). - tigr graphics backend (`tvg`): the same view tree rendered in a window. Text uses a bundled 8x16 monospaced VGA font (`tvfont`, public-domain IBM VGA glyphs) so no system font is needed; box drawing is line segments; tigr keyboard/mouse are mapped to tv events. `tv.InitVirtual` lets any driver set the virtual screen size without touching the terminal. - Menu bar with drop-down menus: click or `F10` to open, Left/Right switch menus, Up/Down move, Enter/Space or click selects (returns the item tag); separators supported. ## Verified Driving the demo through a pty and reconstructing the screen: - initial layout (Editor + About windows, list, radios, check box, buttons, status bar) renders correctly; - clicking `OK` with the mouse opens the modal Info box; - dragging the title moves the window in every direction and clamps at the top-left so the title stays visible; - clicking the `File` title opens the drop-down (New/Open/Sep/Quit), `F10` + Enter selects the first item (status shows the command tag), and clicking `Quit` exits the program. ## Known limitations / next steps - Menu items have no hotkeys; no check/radio menu items. - No form validation or file/directory dialog. - The graphics window uses integer scaling (TIGR_FIXED); no per-window font size or resizable grid yet. - Windows are not resizable; no hover highlight. - Terminal size is polled (no `SIGWINCH`-driven relayout). - Nested clipping groups beyond windows are untested. ## GNU Modula-2 notes See `README.md`: value-returning no-arg procedures need `()` in the `.def`; pointer fields need `^`; a `BEGIN...END` block cannot be a `CASE` branch; `INTEGER` vs `HIGH()` comparisons need `VAL`; termios/winsize use fixed Linux offsets. A subtle runtime bug was found and fixed in the ANSI output: SGR attributes accumulate, so blink must be emitted explicitly as `;5`/`;25` or it leaks into every following cell.