Repository: microsoft/terminal
File: src/host/readDataCooked.cpp (C++)

Code before:
    const auto area = w * h;

    auto off = w * pos.y + pos.x;
    off += distance;
    off = off < 0 ? 0 : (off > area ? area : off);

    return {
        gsl::narrow_cast<til::CoordType>(off % w),
        gsl::narrow_cast<til::CoordType>(off / w),
    };
}

// This moves the cursor `distance`-many cells back up in the buffer.
// It's intended to be used in combination with _writeChars.
void COOKED_READ_DATA::_offsetCursorPosition(ptrdiff_t distance) const
{
    if (distance != 0)
    {
        _offsetCursorPositionAlways(distance);
    }
}

void COOKED_READ_DATA::_offsetCursorPositionAlways(ptrdiff_t distance) const
{
    const auto& textBuffer = _screenInfo.GetTextBuffer();
    const auto& cursor = textBuffer.GetCursor();
    const auto pos = _offsetPosition(cursor.GetPosition(), distance);

    std::ignore = _screenInfo.SetCursorPosition(pos, true);
    _screenInfo.MakeCursorVisible(pos);
}

til::CoordType COOKED_READ_DATA::_getColumnAtRelativeCursorPosition(ptrdiff_t distance) const
{
    const auto& textBuffer = _screenInfo.GetTextBuffer();
    const auto size = _screenInfo.GetTextBuffer().GetSize().Dimensions();
    const auto& cursor = textBuffer.GetCursor();
    const auto pos = cursor.GetPosition();

    auto x = gsl::narrow_cast<til::CoordType>((pos.x + distance) % size.width);
    if (x < 0)
    {
        x += size.width;
    }

    return x;
}

// If the viewport is large enough to fit a popup, this function prepares everything for
// showing the given type. It handles computing the size of the popup, its position,
// backs the affected area up and draws the border and initial contents.

Review comment (suggestion):
Would appreciate a method description here! Just to explain why this and `_offsetCursorPosition` can't be combined into one function. The comment you added in `readDataCooked.cpp` explains it but if someone looks at this file on its own in the future it seems confusing.

Code after:
    const auto area = w * h;

    auto off = w * pos.y + pos.x;
    off += distance;
    off = off < 0 ? 0 : (off > area ? area : off);

    return {
        gsl::narrow_cast<til::CoordType>(off % w),
        gsl::narrow_cast<til::CoordType>(off / w),
    };
}

// See _offsetCursorPositionAlways(). This wrapper is just here to avoid doing
// expensive cursor movements when there's nothing to move. A no-op wrapper.
void COOKED_READ_DATA::_offsetCursorPosition(ptrdiff_t distance) const
{
    if (distance != 0)
    {
        _offsetCursorPositionAlways(distance);
    }
}

// This moves the cursor `distance`-many cells around in the buffer.
// It's intended to be used in combination with _writeChars.
// Usually you should use _offsetCursorPosition() to no-op distance==0.
void COOKED_READ_DATA::_offsetCursorPositionAlways(ptrdiff_t distance) const
{
    const auto& textBuffer = _screenInfo.GetTextBuffer();
    const auto& cursor = textBuffer.GetCursor();
    const auto pos = _offsetPosition(cursor.GetPosition(), distance);

    std::ignore = _screenInfo.SetCursorPosition(pos, true);
    _screenInfo.MakeCursorVisible(pos);
}

til::CoordType COOKED_READ_DATA::_getColumnAtRelativeCursorPosition(ptrdiff_t distance) const
{
    const auto& textBuffer = _screenInfo.GetTextBuffer();
    const auto size = _screenInfo.GetTextBuffer().GetSize().Dimensions();
    const auto& cursor = textBuffer.GetCursor();
    const auto pos = cursor.GetPosition();

    auto x = gsl::narrow_cast<til::CoordType>((pos.x + distance) % size.width);
    if (x < 0)
    {
        x += size.width;
    }

    return x;
}