in src/terminal/parser/OutputStateMachineEngine.cpp [427:638]
bool OutputStateMachineEngine::ActionCsiDispatch(const VTID id, const VTParameters parameters)
{
bool success = false;
switch (id)
{
case CsiActionCodes::CUU_CursorUp:
success = _dispatch->CursorUp(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CUU);
break;
case CsiActionCodes::CUD_CursorDown:
success = _dispatch->CursorDown(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CUD);
break;
case CsiActionCodes::CUF_CursorForward:
success = _dispatch->CursorForward(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CUF);
break;
case CsiActionCodes::CUB_CursorBackward:
success = _dispatch->CursorBackward(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CUB);
break;
case CsiActionCodes::CNL_CursorNextLine:
success = _dispatch->CursorNextLine(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CNL);
break;
case CsiActionCodes::CPL_CursorPrevLine:
success = _dispatch->CursorPrevLine(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CPL);
break;
case CsiActionCodes::CHA_CursorHorizontalAbsolute:
case CsiActionCodes::HPA_HorizontalPositionAbsolute:
success = _dispatch->CursorHorizontalPositionAbsolute(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CHA);
break;
case CsiActionCodes::VPA_VerticalLinePositionAbsolute:
success = _dispatch->VerticalLinePositionAbsolute(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::VPA);
break;
case CsiActionCodes::HPR_HorizontalPositionRelative:
success = _dispatch->HorizontalPositionRelative(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::HPR);
break;
case CsiActionCodes::VPR_VerticalPositionRelative:
success = _dispatch->VerticalPositionRelative(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::VPR);
break;
case CsiActionCodes::CUP_CursorPosition:
case CsiActionCodes::HVP_HorizontalVerticalPosition:
success = _dispatch->CursorPosition(parameters.at(0), parameters.at(1));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CUP);
break;
case CsiActionCodes::DECSTBM_SetScrollingRegion:
success = _dispatch->SetTopBottomScrollingMargins(parameters.at(0).value_or(0), parameters.at(1).value_or(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::DECSTBM);
break;
case CsiActionCodes::ICH_InsertCharacter:
success = _dispatch->InsertCharacter(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::ICH);
break;
case CsiActionCodes::DCH_DeleteCharacter:
success = _dispatch->DeleteCharacter(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::DCH);
break;
case CsiActionCodes::ED_EraseDisplay:
success = parameters.for_each([&](const auto eraseType) {
return _dispatch->EraseInDisplay(eraseType);
});
TermTelemetry::Instance().Log(TermTelemetry::Codes::ED);
break;
case CsiActionCodes::EL_EraseLine:
success = parameters.for_each([&](const auto eraseType) {
return _dispatch->EraseInLine(eraseType);
});
TermTelemetry::Instance().Log(TermTelemetry::Codes::EL);
break;
case CsiActionCodes::DECSET_PrivateModeSet:
success = parameters.for_each([&](const auto mode) {
return _dispatch->SetMode(DispatchTypes::DECPrivateMode(mode));
});
//TODO: MSFT:6367459 Add specific logging for each of the DECSET/DECRST codes
TermTelemetry::Instance().Log(TermTelemetry::Codes::DECSET);
break;
case CsiActionCodes::DECRST_PrivateModeReset:
success = parameters.for_each([&](const auto mode) {
return _dispatch->ResetMode(DispatchTypes::DECPrivateMode(mode));
});
TermTelemetry::Instance().Log(TermTelemetry::Codes::DECRST);
break;
case CsiActionCodes::SGR_SetGraphicsRendition:
success = _dispatch->SetGraphicsRendition(parameters);
TermTelemetry::Instance().Log(TermTelemetry::Codes::SGR);
break;
case CsiActionCodes::DSR_DeviceStatusReport:
success = _dispatch->DeviceStatusReport(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::DSR);
break;
case CsiActionCodes::DA_DeviceAttributes:
success = parameters.at(0).value_or(0) == 0 && _dispatch->DeviceAttributes();
TermTelemetry::Instance().Log(TermTelemetry::Codes::DA);
break;
case CsiActionCodes::DA2_SecondaryDeviceAttributes:
success = parameters.at(0).value_or(0) == 0 && _dispatch->SecondaryDeviceAttributes();
TermTelemetry::Instance().Log(TermTelemetry::Codes::DA2);
break;
case CsiActionCodes::DA3_TertiaryDeviceAttributes:
success = parameters.at(0).value_or(0) == 0 && _dispatch->TertiaryDeviceAttributes();
TermTelemetry::Instance().Log(TermTelemetry::Codes::DA3);
break;
case CsiActionCodes::DECREQTPARM_RequestTerminalParameters:
success = _dispatch->RequestTerminalParameters(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::DECREQTPARM);
break;
case CsiActionCodes::SU_ScrollUp:
success = _dispatch->ScrollUp(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::SU);
break;
case CsiActionCodes::SD_ScrollDown:
success = _dispatch->ScrollDown(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::SD);
break;
case CsiActionCodes::ANSISYSSC_CursorSave:
success = parameters.empty() && _dispatch->CursorSaveState();
TermTelemetry::Instance().Log(TermTelemetry::Codes::ANSISYSSC);
break;
case CsiActionCodes::ANSISYSRC_CursorRestore:
success = parameters.empty() && _dispatch->CursorRestoreState();
TermTelemetry::Instance().Log(TermTelemetry::Codes::ANSISYSRC);
break;
case CsiActionCodes::IL_InsertLine:
success = _dispatch->InsertLine(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::IL);
break;
case CsiActionCodes::DL_DeleteLine:
success = _dispatch->DeleteLine(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::DL);
break;
case CsiActionCodes::CHT_CursorForwardTab:
success = _dispatch->ForwardTab(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CHT);
break;
case CsiActionCodes::CBT_CursorBackTab:
success = _dispatch->BackwardsTab(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::CBT);
break;
case CsiActionCodes::TBC_TabClear:
success = parameters.for_each([&](const auto clearType) {
return _dispatch->TabClear(clearType);
});
TermTelemetry::Instance().Log(TermTelemetry::Codes::TBC);
break;
case CsiActionCodes::ECH_EraseCharacters:
success = _dispatch->EraseCharacters(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::ECH);
break;
case CsiActionCodes::DTTERM_WindowManipulation:
success = _dispatch->WindowManipulation(parameters.at(0), parameters.at(1), parameters.at(2));
TermTelemetry::Instance().Log(TermTelemetry::Codes::DTTERM_WM);
break;
case CsiActionCodes::REP_RepeatCharacter:
// Handled w/o the dispatch. This function is unique in that way
// If this were in the ITerminalDispatch, then each
// implementation would effectively be the same, calling only
// functions that are already part of the interface.
// Print the last graphical character a number of times.
if (_lastPrintedChar != AsciiChars::NUL)
{
const size_t repeatCount = parameters.at(0);
std::wstring wstr(repeatCount, _lastPrintedChar);
_dispatch->PrintString(wstr);
}
success = true;
TermTelemetry::Instance().Log(TermTelemetry::Codes::REP);
break;
case CsiActionCodes::DECSCUSR_SetCursorStyle:
success = _dispatch->SetCursorStyle(parameters.at(0));
TermTelemetry::Instance().Log(TermTelemetry::Codes::DECSCUSR);
break;
case CsiActionCodes::DECSTR_SoftReset:
success = _dispatch->SoftReset();
TermTelemetry::Instance().Log(TermTelemetry::Codes::DECSTR);
break;
case CsiActionCodes::XT_PushSgr:
case CsiActionCodes::XT_PushSgrAlias:
success = _dispatch->PushGraphicsRendition(parameters);
TermTelemetry::Instance().Log(TermTelemetry::Codes::XTPUSHSGR);
break;
case CsiActionCodes::XT_PopSgr:
case CsiActionCodes::XT_PopSgrAlias:
success = _dispatch->PopGraphicsRendition();
TermTelemetry::Instance().Log(TermTelemetry::Codes::XTPOPSGR);
break;
default:
// If no functions to call, overall dispatch was a failure.
success = false;
break;
}
// If we were unable to process the string, and there's a TTY attached to us,
// trigger the state machine to flush the string to the terminal.
if (_pfnFlushToTerminal != nullptr && !success)
{
success = _pfnFlushToTerminal();
}
_ClearLastChar();
return success;
}