A VT/xterm-compatible terminal emulator framework written in Free Pascal,
with fpGUI, LCL (Lazarus), and GTK4 © front-ends. Designed as a
reusable library: the backend, VT parser, and view widgets are independent
units that can be composed into other applications. The GTK4 path goes
through a C ABI shim (libtermview.so) so any C/C++/Vala/Rust host can
embed it.
-
VT100 / xterm parser: SGR colors (16 / 256 / truecolor), bold / faint / italic / underline / blink / inverse / hidden / strike, double-width / CJK, combining marks, scroll regions, alternate buffer, sync update (
?2026). -
Input: mouse reporting (
?9/?1000/?1002/?1003, SGR + legacy encoding), bracketed paste (?2004), OSC 52 clipboard read/write,Shiftbypass for native selection. -
Backends: Unix (forkpty) and Windows (ConPTY); the same Controller drives either.
-
fpGUI and LCL widgets: scrollback, font + emoji-font fallback, configurable cursor style, palette, and selection colors. Right-click context menu with Copy / Paste / Font / Emoji Font. The Copy/Paste items collaborate with bracketed-paste-aware apps: when the running app has enabled
?2004, Copy forwardsCtrl+Shift+C(CSI u) and Paste forwardsCtrl+Shift+Vso the app can run its own clipboard handlers (and answer back via OSC 52). Paste enables/disables based on actual clipboard contents (text — plus image formats on the LCL view). -
YieldRightClickToAppproperty (both views): defaultFalsekeeps the context menu working even in fullscreen TUIs; setTrueto forward right-clicks into a mouse-capturing app. -
HTML export:
Core.GetHtmlSelection / GetHtmlScreen / GetHtmlAll(and the lower-levelGetHtmlRange) produce a self-contained styled document (colors, bold, italic, underline, strike, faint, inverse, hidden, blink, wide cells). Soft-wrapped physical rows are joined into one logical line; trailing blank cells and trailing blank rows are trimmed. Page title comes from the host form. Both views expose three Copy as HTML items (Selection / Screen / Everything). -
Subprocess detection:
Controller.SubProcessRunningreturnsTruewhen the shell has handed the PTY off to a foreground child (build, editor, REPL). Unix-only; backed bytcgetpgrp(master_fd). Both example apps use it in anOnCloseQueryhook to confirm window-close while a command is in flight. -
No platform-specific paths or hardcoded debug files. Optional tracing gated on env vars (see Debug).
TerminalFramework/ Core library (parser, screen model, PTY backends)
ViewfpGUI/ fpGUI widget that renders a TTerminalController
ViewLCL/ LCL (Lazarus) widget that renders a TTerminalController
LibTermView/ Pascal -> C ABI shim (libtermview.so / .a + termview.h)
ViewGtk4/ GTK4 widget written in C, built on LibTermView
ExampleTerminal/ Minimal fpGUI demo app
ExampleTerminalLCL/ Minimal LCL demo app (lazbuild script + pasbuild module)
ExampleTerminalGtk4/ Minimal GTK4 demo app written in C
tools/replay/ Trace-replay tool for parser debugging
tools/build-win64.sh Cross-compile script for Windows x86_64
tools/sgr-demo.sh Bash script exercising SGR features
Makefile Build everything; reports per-module pass/fail summary-
Free Pascal Compiler 3.3.1 or newer (3.2.2 may work but is untested).
-
pasbuild — the Maven-style build tool used for module orchestration.
-
fpGUI Toolkit 2.1 or newer, installed through pasbuild (the build will look for it in
~/.pasbuild/repository) — only required for the fpGUI view + example. -
Lazarus / LCL checkout — only required for the LCL view + example.
MakefileandViewLCL/project.xmlcurrently point at~/Programming/Tools/lazarus-gitlab/; adjust to match your tree. -
For Win64 cross-compile: FPC’s
-Twin64target (bundled with default FPC on Linux; no extra mingw needed for our use).
The top-level Makefile attempts every module and prints a pass/fail
summary at the end (continues past failures so you can see everything in
one run):
make
./ExampleTerminal/target/exampleterminal # fpGUI demo
./ExampleTerminalLCL/target/exampleterminallcl # LCL demoPer-module via pasbuild directly:
pasbuild compile -f project.xml -m TerminalFramework -p debug
pasbuild compile -f project.xml -m ViewfpGUI -p debug
pasbuild compile -f project.xml -m ViewLCL -p debug
pasbuild compile -f project.xml -m ExampleTerminal -p debug
pasbuild compile -f project.xml -m ExampleTerminalLCL -p debugThe LCL example can also be built through Lazarus tooling:
./ExampleTerminalLCL/build.sh # wraps lazbuild + registers the .lpk depsThree pieces: a PIC-compiled Pascal shared library (libtermview.so), a
GTK4 widget written in C (libtermviewgtk4.so), and the C demo. Each has
its own build.sh; make chains them.
make gtk4
./ExampleTerminalGtk4/target/exampleterminalgtk4Requires GTK4 ≥ 4.10 (uses GtkPopoverMenu, GtkScrollable, async
clipboard) and pkg-config gtk4 pangocairo. Embedders include
<termview.h> (the C ABI) and/or <term_view_widget.h> (the widget),
linking -ltermview -ltermviewgtk4.
Requires the fpGUI Win64 ppus at
~/.pasbuild/repository/fpgui-framework/2.1.0/x86_64-win64-3.3.1/.
Build fpGUI itself for that target first (same pasbuild command with
-Twin64 -Px86_64 flags appended).
tools/build-win64.sh
# -> target/win64/ExampleTerminal.exeThe script wraps fpc -Twin64 -Px86_64 -WG (GUI subsystem) and is
intentionally short — adapt it freely.
Embed the controller and view. fpGUI:
uses Terminal.Controller, Terminal.View.fpGUI;
FController := TTerminalController.Create(80, 25, 5000); { cols, rows, scrollback }
TerminalView.AttachController(FController);
TerminalView.StartShell; { defaults to user's shell }
TerminalView.StartShell('/bin/zsh'); { or an explicit path }LCL — identical, just use the LCL widget. Interfaces must be the first
unit in your program to select a widgetset:
program MyTerm;
uses
Interfaces, Forms,
Terminal.Controller, Terminal.View.LCL;
var
Frm: TTerminalLCLForm;
begin
Application.Initialize;
Application.CreateForm(TTerminalLCLForm, Frm);
Frm.TerminalView.AttachController(TTerminalController.Create(80, 25, 5000));
Frm.TerminalView.StartShell;
Application.Run;
end.On Windows the default-shell search order is Git Bash → MSYS2 bash →
Cygwin bash → %COMSPEC% (cmd.exe).
Both traces are off by default. Enable with environment variables:
TERM_TRACE=/path/to/file-
Per-operation log from the screen model (cursor moves, SGR, scrolls).
TERM_RAW_TRACE=/path/to/file-
Raw PTY byte chunks with hex + ASCII annotations. Useful with
tools/replayto deterministically reproduce a parser bug.
BSD 3-Clause. See LICENSE.