void StandardCalculatorViewModel::OnPaste()

in src/CalcViewModel/StandardCalculatorViewModel.cpp [731:881]


void StandardCalculatorViewModel::OnPaste(String ^ pastedString)
{
    // If pastedString is invalid("NoOp") then display pasteError else process the string
    if (CopyPasteManager::IsErrorMessage(pastedString))
    {
        this->DisplayPasteError();
        return;
    }

    TraceLogger::GetInstance()->LogInputPasted(GetCalculatorMode());
    bool isFirstLegalChar = true;
    m_standardCalculatorManager.SendCommand(Command::CommandCENTR);
    bool sendNegate = false;
    bool processedDigit = false;
    bool sentEquals = false;
    bool isPreviousOperator = false;

    vector<bool> negateStack;

    // Iterate through each character pasted, and if it's valid, send it to the model.
    auto it = pastedString->Begin();

    while (it != pastedString->End())
    {
        bool sendCommand = true;
        auto buttonInfo = MapCharacterToButtonId(*it);

        NumbersAndOperatorsEnum mappedNumOp = buttonInfo.buttonId;
        bool canSendNegate = buttonInfo.canSendNegate;

        if (mappedNumOp == NumbersAndOperatorsEnum::None)
        {
            ++it;
            continue;
        }

        if (isFirstLegalChar || isPreviousOperator)
        {
            isFirstLegalChar = false;
            isPreviousOperator = false;

            // If the character is a - sign, send negate
            // after sending the next legal character.  Send nothing now, or
            // it will be ignored.
            if (NumbersAndOperatorsEnum::Subtract == mappedNumOp)
            {
                sendNegate = true;
                sendCommand = false;
            }

            // Support (+) sign prefix
            if (NumbersAndOperatorsEnum::Add == mappedNumOp)
            {
                sendCommand = false;
            }
        }

        switch (mappedNumOp)
        {
            // Opening parenthesis starts a new expression and pushes negation state onto the stack
        case NumbersAndOperatorsEnum::OpenParenthesis:
            negateStack.push_back(sendNegate);
            sendNegate = false;
            break;

            // Closing parenthesis pops the negation state off the stack and sends it down to the calc engine
        case NumbersAndOperatorsEnum::CloseParenthesis:
            if (!negateStack.empty())
            {
                sendNegate = negateStack.back();
                negateStack.pop_back();
                canSendNegate = true;
            }
            else
            {
                // Don't send a closing parenthesis if a matching opening parenthesis hasn't been sent already
                sendCommand = false;
            }
            break;

        case NumbersAndOperatorsEnum::Zero:
        case NumbersAndOperatorsEnum::One:
        case NumbersAndOperatorsEnum::Two:
        case NumbersAndOperatorsEnum::Three:
        case NumbersAndOperatorsEnum::Four:
        case NumbersAndOperatorsEnum::Five:
        case NumbersAndOperatorsEnum::Six:
        case NumbersAndOperatorsEnum::Seven:
        case NumbersAndOperatorsEnum::Eight:
        case NumbersAndOperatorsEnum::Nine:
            processedDigit = true;
            break;

        case NumbersAndOperatorsEnum::Add:
        case NumbersAndOperatorsEnum::Subtract:
        case NumbersAndOperatorsEnum::Multiply:
        case NumbersAndOperatorsEnum::Divide:
            isPreviousOperator = true;
            break;
        }

        if (sendCommand)
        {
            sentEquals = (mappedNumOp == NumbersAndOperatorsEnum::Equals);
            Command cmdenum = ConvertToOperatorsEnum(mappedNumOp);
            m_standardCalculatorManager.SendCommand(cmdenum);

            // The CalcEngine state machine won't allow the negate command to be sent before any
            // other digits, so instead a flag is set and the command is sent after the first appropriate
            // command.
            if (sendNegate)
            {
                if (canSendNegate)
                {
                    Command cmdNegate = ConvertToOperatorsEnum(NumbersAndOperatorsEnum::Negate);
                    m_standardCalculatorManager.SendCommand(cmdNegate);
                }

                // Can't send negate on a leading zero, so wait until the appropriate time to send it.
                if (NumbersAndOperatorsEnum::Zero != mappedNumOp && NumbersAndOperatorsEnum::Decimal != mappedNumOp)
                {
                    sendNegate = false;
                }
            }
        }

        // Handle exponent and exponent sign (...e+... or ...e-... or ...e...)
        if (mappedNumOp == NumbersAndOperatorsEnum::Exp)
        {
            // Check the following item
            switch (MapCharacterToButtonId(*(it + 1)).buttonId)
            {
            case NumbersAndOperatorsEnum::Subtract:
            {
                Command cmdNegate = ConvertToOperatorsEnum(NumbersAndOperatorsEnum::Negate);
                m_standardCalculatorManager.SendCommand(cmdNegate);
                ++it;
            }
            break;
            case NumbersAndOperatorsEnum::Add:
            {
                // Nothing to do, skip to the next item
                ++it;
            }
            break;
            }
        }

        ++it;
    }
}