Something went wrong. Try again.
The agentic engineering control plane for the posthuman future
Something went wrong. Try again.
3.8 kB · 121 lines
C++
at main
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122#include "CopyMode.h"
#include <algorithm>
CopyCursor applyCopyMotion(CopyCursor cur, CopyMotion motion, int viewportRows, int minRow, int maxRow, int lineLength) { if (maxRow < minRow) { return cur; } // Column clamp: stay inside the row's painted cells (0 when the row is // empty). cursorCol may sit at lineLength-1 at most. const auto clampCol = [lineLength](int col) { return std::clamp(col, 0, std::max(0, lineLength - 1)); }; cur.row = std::clamp(cur.row, minRow, maxRow); switch (motion) { case CopyMotion::Left: // Wrapping left: off the row head steps up to the previous row's end // (vim's h at line start), clamped at the buffer top. if (cur.col > 0) { --cur.col; } else if (cur.row > minRow) { --cur.row; cur.col = std::max(0, lineLength - 1); } break; case CopyMotion::Right: if (cur.col < lineLength - 1) { ++cur.col; } else if (cur.row < maxRow) { ++cur.row; cur.col = 0; } break; case CopyMotion::Up: cur.row = std::max(minRow, cur.row - 1); cur.col = clampCol(cur.col); break; case CopyMotion::Down: cur.row = std::min(maxRow, cur.row + 1); cur.col = clampCol(cur.col); break; case CopyMotion::PageUp: cur.row = std::max(minRow, cur.row - std::max(1, viewportRows)); cur.col = clampCol(cur.col); break; case CopyMotion::PageDown: cur.row = std::min(maxRow, cur.row + std::max(1, viewportRows)); cur.col = clampCol(cur.col); break; case CopyMotion::LineHome: cur.col = 0; break; case CopyMotion::LineEnd: cur.col = std::max(0, lineLength - 1); break; case CopyMotion::BufferTop: cur.row = minRow; cur.col = clampCol(cur.col); break; case CopyMotion::BufferBottom: cur.row = maxRow; cur.col = clampCol(cur.col); break; } cur.row = std::clamp(cur.row, minRow, maxRow); cur.col = clampCol(cur.col); return cur;}
CopySelection normalizeCopySelection(CopyCursor anchor, CopyCursor head) { CopySelection sel; sel.active = true; if (head.row < anchor.row || (head.row == anchor.row && head.col < anchor.col)) { sel.startRow = head.row; sel.startCol = head.col; sel.endRow = anchor.row; sel.endCol = anchor.col; } else { sel.startRow = anchor.row; sel.startCol = anchor.col; sel.endRow = head.row; sel.endCol = head.col; } return sel;}
QString copyYankText(const QVector<QString>& bufferRows, int bufferBaseRow, const CopySelection& sel) { if (!sel.active || sel.endRow < sel.startRow) { return {}; } QString out; for (int row = sel.startRow; row <= sel.endRow; ++row) { // Rows outside the capture window (selection reaching past it) yield // spaces, so the CELL rectangle is preserved at the fixed width. const int index = row - bufferBaseRow; const QString& line = (index >= 0 && index < bufferRows.size()) ? bufferRows[static_cast<qsizetype>(index)] : QString(); const qsizetype width = sel.endCol - sel.startCol + 1; for (qsizetype c = 0; c < width; ++c) { const qsizetype idx = sel.startCol + c; // Blank-pad past a row's painted length (a short line in the rect) // and surrogate halves (a split pair yanks as two spaces rather // than invalid units). if (idx < line.size() && !QChar(line.at(idx)).isHighSurrogate() && !QChar(line.at(idx)).isLowSurrogate()) { out.append(line.at(idx)); } else { out.append(QLatin1Char(' ')); } } if (row != sel.endRow) { out.append(QLatin1Char('\n')); } } return out;}