bool OutputStateMachineEngine::ActionCsiDispatch()

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;
}