This document describes the VT/ANSI sequence parsing and execution system in Windows Terminal. It covers how raw byte streams from applications are parsed into recognized VT sequences, dispatched to appropriate handlers, and executed to modify terminal state.
For information about the terminal control architecture that hosts this system, see Terminal Control Architecture. For details about how the text buffer stores the results of VT operations, see Text Buffer System.
VT sequence processing has four major layers:
StateMachine) — Tokenizes raw byte streams into typed parser actions via IStateMachineEngineOutputStateMachineEngine) — Maps parser actions to typed dispatch callsITermDispatch / AdaptDispatch) — Executes recognized sequences against terminal stateITerminalApi) — Abstracts buffer and state access; separate implementations exist for Windows Terminal and conhostComponent map from source files to runtime objects:
Diagram: Class hierarchy and file locations for VT sequence processing
Sources: src/terminal/parser/stateMachine.hpp src/terminal/parser/OutputStateMachineEngine.hpp1-55 src/terminal/adapter/adaptDispatch.hpp1-50 src/terminal/adapter/ITerminalApi.hpp src/terminal/adapter/termDispatch.hpp src/terminal/adapter/ITermDispatch.hpp
The complete flow from raw bytes to screen updates follows this path:
Diagram: VT Sequence Processing Data Flow
Sources: src/terminal/parser/OutputStateMachineEngine.cpp49-326 src/terminal/adapter/adaptDispatch.cpp40-196
The StateMachine class implements a state-based parser following the VT specification. It processes input character by character, transitioning between states based on character values.
| State | Purpose | Example Triggers |
|---|---|---|
Ground | Normal text printing | Printable characters |
Escape | ESC sequence start | \x1b (ESC) |
CsiEntry | CSI sequence start | ESC + <FileRef file-url="https://github.com/microsoft/terminal/blob/83d0d9df/ |
The OutputStateMachineEngine implements IStateMachineEngine and translates state machine actions into dispatch calls. It recognizes specific VT sequences by their identifiers (intermediate characters + final character).
The engine provides several action methods called by the state machine:
| Method | Purpose | Example Sequences |
|---|---|---|
ActionPrint() | Print single character | Regular text |
ActionPrintString() | Print text runs | Optimized bulk printing |
ActionExecute() | Execute C0 controls | \t, \r, \n, \b |
ActionEscDispatch() | Simple ESC sequences | ESC D (IND), ESC M (RI) |
ActionCsiDispatch() | CSI sequences | CSI A (CUU), CSI H (CUP) |
ActionOscDispatch() | OSC sequences | OSC title, color table |
Sequences are identified using VTID - a 64-bit identifier encoding intermediate and final characters:
Diagram: VTID Sequence Identification
Example dispatch logic from src/terminal/parser/OutputStateMachineEngine.cpp406-450:
Sources: src/terminal/parser/OutputStateMachineEngine.cpp192-850 src/terminal/adapter/DispatchTypes.hpp10-105
ITermDispatch (src/terminal/adapter/ITermDispatch.hpp) is the pure virtual interface that OutputStateMachineEngine calls when it recognizes a sequence. It declares callbacks for every VT operation: Print, PrintString, CursorUp, SetGraphicsRendition, EraseInDisplay, SetMode, and many more.
TermDispatch (src/terminal/adapter/termDispatch.hpp) provides no-op default implementations for all methods except Print and PrintString, which remain pure virtual. It is useful for constructing test doubles and specialized dispatch implementations that only need to handle a subset of sequences.
AdaptDispatch does not extend TermDispatch; it implements ITermDispatch directly (src/terminal/adapter/adaptDispatch.hpp33). The class hierarchy is:
| Class | File | Role |
|---|---|---|
ITermDispatch | src/terminal/adapter/ITermDispatch.hpp | Pure interface — all VT operation callbacks |
TermDispatch | src/terminal/adapter/termDispatch.hpp | No-op defaults for optional operations; used in tests |
AdaptDispatch | src/terminal/adapter/adaptDispatch.hpp | Full production implementation for both conhost and Terminal |
ITermDispatch also defines an OptionalFeature enum with values ChecksumReport and ClipboardWrite. These gate behaviors that can be toggled at runtime via SetOptionalFeatures(), called from Terminal::SetOptionalFeatures() src/cascadia/TerminalCore/Terminal.cpp248-255
Sources: src/terminal/adapter/ITermDispatch.hpp src/terminal/adapter/termDispatch.hpp22-50 src/terminal/adapter/adaptDispatch.hpp33-49
AdaptDispatch implements ITermDispatch and provides the actual VT sequence execution logic. It modifies terminal state through the ITerminalApi interface.
Diagram: AdaptDispatch Internal Components
Sources: src/terminal/adapter/adaptDispatch.hpp193-330 src/terminal/adapter/adaptDispatch.cpp40-49
The Print() and PrintString() methods handle character output with translation:
_termOutput.TranslateKey() handles character set mappings_WriteToBuffer() writes to the active page's text bufferSources: src/terminal/adapter/adaptDispatch.cpp57-196
Cursor movement methods (CursorUp, CursorDown, etc.) use a common helper:
Diagram: Cursor Movement Processing
Key logic from src/terminal/adapter/adaptDispatch.cpp322-397:
Sources: src/terminal/adapter/adaptDispatch.cpp207-446
Erase operations (EraseInDisplay, EraseInLine) follow this pattern:
_GetEraseAttributes() gets fill color based on erase color mode_FillRect() fills area with spaces and erase attributesSources: src/terminal/adapter/adaptDispatch.cpp730-813
SetGraphicsRendition() processes SGR parameters to update text attributes:
Diagram: SGR Parameter Processing
Sources: src/terminal/adapter/adaptDispatch.cpp1500-1800
Scrolling is handled through _ScrollRectVertically() and _ScrollRectHorizontally():
Vertical Scrolling:
TextBuffer::ScrollRows()OutputCell iterationHorizontal Scrolling:
Sources: src/terminal/adapter/adaptDispatch.cpp544-685
ITerminalApi (src/terminal/adapter/ITerminalApi.hpp) decouples AdaptDispatch from specific terminal implementations. It provides:
| Method category | Example methods |
|---|---|
| Buffer and viewport access | GetBufferAndViewport, SetViewportPosition |
| System mode management | SetSystemMode, GetSystemMode |
| Response output | ReturnResponse, ReturnAnswerback |
| Side-effect notifications | WarningBell, SetWindowTitle, CopyToClipboard, SetTaskbarProgress, ShowWindow |
| Alternate screen buffer | UseAlternateScreenBuffer, UseMainScreenBuffer |
There are two production implementations:
| Implementation | File | Used in |
|---|---|---|
Terminal | src/cascadia/TerminalCore/Terminal.hpp | Windows Terminal engine |
ConhostInternalGetSet | src/host/outputStream.hpp | conhost.exe |
Terminal implements ITerminalApi directly — it is one of three interfaces the class satisfies src/cascadia/TerminalCore/Terminal.hpp54-58 When Terminal::Create() constructs AdaptDispatch, it passes *this as the ITerminalApi& argument src/cascadia/TerminalCore/Terminal.cpp43-55 The ITerminalApi method bodies reside in src/cascadia/TerminalCore/TerminalApi.cpp. For example, ReturnResponse invokes the _pfnWriteInput callback registered by ControlCore, routing the response string back to the connected process src/cascadia/TerminalCore/TerminalApi.cpp23-29
ConhostInternalGetSet src/host/outputStream.hpp wraps an IIoProvider reference to access SCREEN_INFORMATION and the console input buffer. Its ReturnResponse writes directly into the console input buffer via WriteString src/host/outputStream.cpp34-48 Unlike the Terminal path, it suppresses responses when running in ConPTY mode (IsInVtIoMode()).
Sources: src/terminal/adapter/ITerminalApi.hpp src/cascadia/TerminalCore/Terminal.hpp54-58 src/cascadia/TerminalCore/TerminalApi.cpp23-29 src/host/outputStream.hpp src/host/outputStream.cpp22-48
AdaptDispatch maintains several types of state:
Stored in _modes enumset:
| Mode | Effect |
|---|---|
InsertReplace | IRM - Insert vs. replace characters |
Origin | DECOM - Cursor positioning relative to margins |
Column | DECCOLM - 80/132 column mode |
EraseColor | DECSCNM - Erase uses background color |
PageCursorCoupling | DECPCCM - Cursor moves with page changes |
Two CursorState instances for main and alternate buffers:
Sources: src/terminal/adapter/adaptDispatch.hpp211-220 src/terminal/adapter/adaptDispatch.cpp453-512
The _scrollMargins rect defines the scrolling region:
Sources: src/terminal/adapter/adaptDispatch.cpp271-314
The VT processing stack is initialized differently in Windows Terminal vs. conhost.
Terminal::Create() src/cascadia/TerminalCore/Terminal.cpp43-55 constructs the full stack inline, passing *this (the Terminal instance) as the ITerminalApi to AdaptDispatch:
Diagram: Windows Terminal VT stack initialization in Terminal::Create()
The Terminal object is simultaneously the owner of _stateMachine and the ITerminalApi implementation that AdaptDispatch calls back into.
SCREEN_INFORMATION::_InitializeOutputStateMachine() src/host/screenInfo.cpp225-264 creates a ConhostInternalGetSet as the ITerminalApi adapter and builds the same wrapping chain:
Diagram: conhost VT stack initialization in SCREEN_INFORMATION
Sources: src/cascadia/TerminalCore/Terminal.cpp43-55 src/host/screenInfo.cpp225-264 src/host/outputStream.hpp
VT sequences reach the state machine through two main paths:
For ConPTY and virtual terminal mode:
Diagram: WriteConsole VT Processing Path
From src/host/_stream.cpp22-29 and src/host/_stream.h23:
WriteCharsVT() sends strings directly to StateMachine::ProcessString()ENABLE_VIRTUAL_TERMINAL_PROCESSING is enabledFor terminal emulators receiving ConPTY output:
Diagram: ConPTY to Terminal Path
Sources: src/cascadia/TerminalCore/Terminal.cpp458-461 src/cascadia/TerminalControl/ControlCore.cpp302-356
Consider the sequence \x1b<FileRef file-url="https://github.com/microsoft/terminal/blob/83d0d9df/2J (erase display)#L1-LNaN" min=1 file-path="2J` (erase display)">Hii src/terminal/adapter/adaptDispatch.cpp730-782
The engine provides ActionPrintString() to process runs of printable characters in bulk rather than character-by-character:
TextBuffer::Replace()Sources: src/terminal/parser/OutputStateMachineEngine.cpp147-164
VT parameters use efficient storage:
VTParameter - Lightweight wrapper around VTInt with optional semanticsVTParameters - Span-based parameter array with subparameter supportSources: src/terminal/adapter/DispatchTypes.hpp107-280
AdaptDispatch optimizes buffer access:
FillRect() for erases)Sources: src/terminal/adapter/adaptDispatch.cpp696-720
The VT sequence processing system provides a clean separation between parsing, recognition, and execution:
This architecture allows the same parsing and dispatch logic to be shared across Windows Console (conhost.exe) and Windows Terminal while maintaining flexibility in implementation details.
Sources: src/terminal/parser/OutputStateMachineEngine.cpp1-26 src/terminal/adapter/adaptDispatch.cpp1-49 src/host/screenInfo.cpp225-264
Refresh this wiki
This wiki was recently refreshed. Please wait 4 days to refresh again.