# tvision-m2 - a TVision/Turbo-Vision style toolkit in GNU Modula-2 A character-cell UI toolkit written in ISO GNU Modula-2 (`gm2 -fiso`) that runs in a terminal (xterm and friends). It is a small, self-contained Turbo-Vision-like library: a retained view tree with clipping and z-order, a diffed ANSI cell screen, keyboard and mouse decoding (xterm SGR mouse reports), widgets, and modal dialogs. Everything is Modula-2 except `tvtty.def`, the tiny libc binding used to put the terminal in raw mode and to query its size (`termios`, `ioctl`, `read`, `write`). There is no C source and no graphics dependency. ## Files | file | role | |---|---| | `tvtty.def` | libc binding (raw mode, winsize, read/write) | | `tv.def` / `tv.mod` | the toolkit: screen, view tree, widgets, events | | `tvg.def` / `tvg.mod` | tigr graphics backend (renders the view tree in a window) | | `tvfont.def` / `tvfont.mod` | bundled 8x16 monospaced bitmap font for the backend | | `demo.mod` | demo application | | `ttysize.mod` | diagnostic: checks the tty binding | ## Build & run gm2 -fiso -c tvtty.def gm2 -fiso -I. -c tv.mod gm2 -fiso -I. tv.o demo.mod -o demo ./demo make -C examples or simply `make`. The graphics example needs the tigr object from the sibling project: make tvg.o tvfont.o make -C examples gfx ./examples/gfx Run it from a real terminal; `Esc` exits. See `TUTORIAL.md` to write your own and `API.md` for the full reference. ## What works - Alternate screen, hidden/show cursor, terminal restored on exit. - 16-colour foreground/background with blink; UTF-8 output (box-drawing). - Perspective view tree: groups and windows contain children; drawing is clipped to each window; overlapping windows are ordered (z-order) and the one you click comes to the front. - Windows: double-line frame, title, ` X ` close box, draggable by the title bar with the mouse and resizable by the bottom-right `■` handle (`WindowResize`; children flagged `vfExpand` grow with the window). - Menu bar + drop-down menus (mouse and keyboard). - Multi-line editor widget (`VEditor`): insert/overwrite, arrows/Home/End/ PgUp/PgDn, Enter/Backspace/Delete, Tab indent, mouse positioning, wheel scroll, its own Ln/Col/Insert/Modified status row, plus load/save to a file (`EditorLoad`/`EditorSave`). - Syntax highlighting for Modula-2, Pascal and Oberon (keywords, strings, numbers, `(* *)`/`{ }`/`//` comments) and automatic keyword up-casing for Modula-2 and Oberon (`begin` -> `BEGIN`), plus auto-indentation (indent after `BEGIN`/`THEN`/`DO`/..., dedent on `END`/`UNTIL`/`ELSE`). - Widgets: static text, single/double frame, input line (insert, backspace, delete, Home/End/arrows), push button, check box, radio buttons, list box with selection and wheel scrolling, vertical scroll bar. - Focus chain: `Tab`/`Shift-Tab` and up/down cycle widgets; the focused input gets the hardware cursor. - Keyboard decoding: printable UTF-8, arrows, Home/End, PgUp/PgDn, Ins/Del, Tab/Shift-Tab, F1-F12, Enter, Space, Backspace, Esc, Ctrl-C. - Mouse: xterm SGR reporting - click to focus/press, drag window titles, click list rows, wheel-scroll lists. - Diffed redraw (only changed cells are written). - Generic modal dialog builder (`Dialog`/`DlgInput`/`DlgCheck`/`DlgRadio`/ `DlgButton`/`DlgRun`/`DlgTextAt`/`DlgValue`) and `MessageBox` (OK / OK-Cancel / Yes-No), plus the `Message` shorthand. - SIGWINCH-driven resize detection (`Resized`), no polling required. - Optional **tigr graphics backend** (`tvg`): the same views, widgets, menus and dialogs render inside a tigr window (colours, box drawing and text via a bundled 8x16 monospaced VGA font, box drawing as line segments); tigr keyboard/mouse are turned into the same events. Terminal programs stay free of any graphics dependency. - Menu bar with drop-down menus: click a title (or press `F10`), navigate with Left/Right/Up/Down, select with Enter/Space or a mouse click; item separators (`MenuSep`) are supported. The selected item's tag is returned by `HandleEvent`. ## Roadmap ideas - Form validation and a file/directory dialog. - Menu item hotkeys (Alt+letter) and check/radio menu items. - Nested clipping groups and a desktop with many windows / tiling. - Tabs, combo box, progress bar, syntax highlighting, search/replace. - `SIGWINCH`-driven relayout (today the app polls the size). - Mouse hover highlight and resizable windows. ## GNU Modula-2 notes - Value-returning procedures with no parameters need explicit `()` (`PROCEDURE Cols() : INTEGER;`), otherwise the `.def` fails to parse when compiled through the `.mod`. - Pointer fields require `^` (`v^.rect`); there is no implicit dereference. - A compound `BEGIN ... END` block is not a statement, so it cannot appear directly in a `CASE` alternative - use a helper procedure. - An `INTEGER` index compared with `HIGH(array)` (a `CARDINAL`) must be converted: `i <= VAL(INTEGER, HIGH(a))`. - The libc `struct termios`/`struct winsize` are accessed through an opaque byte buffer with fixed Linux offsets (see `tv.mod`).