Skip to content

andrewd207/TerminalEmulator

Repository files navigation

TerminalEmulator

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.

License FPC

Features

  • 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, Shift bypass 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 forwards Ctrl+Shift+C (CSI u) and Paste forwards Ctrl+Shift+V so 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).

  • YieldRightClickToApp property (both views): default False keeps the context menu working even in fullscreen TUIs; set True to forward right-clicks into a mouse-capturing app.

  • HTML export: Core.GetHtmlSelection / GetHtmlScreen / GetHtmlAll (and the lower-level GetHtmlRange) 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.SubProcessRunning returns True when the shell has handed the PTY off to a foreground child (build, editor, REPL). Unix-only; backed by tcgetpgrp(master_fd). Both example apps use it in an OnCloseQuery hook 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).

Repository layout

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

Prerequisites

  • 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. Makefile and ViewLCL/project.xml currently point at ~/Programming/Tools/lazarus-gitlab/; adjust to match your tree.

  • For Win64 cross-compile: FPC’s -Twin64 target (bundled with default FPC on Linux; no extra mingw needed for our use).

Installing pasbuild and fpGUI

# pasbuild from source
git clone https://github.com/graemeg/pasbuild
cd pasbuild
./install.sh        # or follow upstream README

# fpGUI as a pasbuild module
git clone https://github.com/graemeg/fpgui
cd fpgui/framework
pasbuild install -p debug

Building

Linux (or any Unix)

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 demo

Per-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 debug

The LCL example can also be built through Lazarus tooling:

./ExampleTerminalLCL/build.sh   # wraps lazbuild + registers the .lpk deps

GTK4 © build

Three 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/exampleterminalgtk4

Requires 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.

Windows x86_64 (cross-compile from Linux)

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.exe

The script wraps fpc -Twin64 -Px86_64 -WG (GUI subsystem) and is intentionally short — adapt it freely.

Native Windows build

Same project files, but invoke pasbuild from a native FPC install. The Windows backend uses ConPTY, so the resulting binary requires Windows 10 1809 or newer.

Usage

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).

Debug tracing

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/replay to deterministically reproduce a parser bug.

License

BSD 3-Clause. See LICENSE.

About

Terminal Emulator for Linux/Unix's and Win10+

Topics

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors