Various minor bug cleanups.

This commit is contained in:
2025-11-29 21:33:45 -08:00
parent 3de5ec68f8
commit b41946c470
18 changed files with 803 additions and 620 deletions

View File

@@ -26,14 +26,14 @@ TerminalRenderer::Draw(Editor &ed)
int rows, cols;
getmaxyx(stdscr, rows, cols);
// Clear screen
erase();
// Clear screen
erase();
const Buffer *buf = ed.CurrentBuffer();
int content_rows = rows - 1; // last line is status
int saved_cur_y = -1, saved_cur_x = -1; // logical cursor position within content area
if (buf) {
int saved_cur_y = -1, saved_cur_x = -1; // logical cursor position within content area
if (buf) {
const auto &lines = buf->Rows();
std::size_t rowoffs = buf->Rowoffs();
std::size_t coloffs = buf->Coloffs();
@@ -139,113 +139,117 @@ TerminalRenderer::Draw(Editor &ed)
std::size_t rx = buf->Rx(); // render x computed by command layer
int cur_y = static_cast<int>(cy) - static_cast<int>(buf->Rowoffs());
int cur_x = static_cast<int>(rx) - static_cast<int>(buf->Coloffs());
if (cur_y >= 0 && cur_y < content_rows && cur_x >= 0 && cur_x < cols) {
// remember where to leave the terminal cursor after status is drawn
saved_cur_y = cur_y;
saved_cur_x = cur_x;
move(cur_y, cur_x);
}
} else {
mvaddstr(0, 0, "[no buffer]");
}
if (cur_y >= 0 && cur_y < content_rows && cur_x >= 0 && cur_x < cols) {
// remember where to leave the terminal cursor after status is drawn
saved_cur_y = cur_y;
saved_cur_x = cur_x;
move(cur_y, cur_x);
}
} else {
mvaddstr(0, 0, "[no buffer]");
}
// Status line (inverse) — left: app/version/buffer/dirty, middle: message, right: cursor/mark
move(rows - 1, 0);
attron(A_REVERSE);
// Status line (inverse) — left: app/version/buffer/dirty, middle: message, right: cursor/mark
move(rows - 1, 0);
attron(A_REVERSE);
// Fill the status line with spaces first
for (int i = 0; i < cols; ++i) addch(' ');
// Fill the status line with spaces first
for (int i = 0; i < cols; ++i)
addch(' ');
// Build left segment
std::string left;
{
const char *app = "kte";
left.reserve(256);
left += app;
left += " ";
left += KTE_VERSION_STR; // already includes leading 'v'
const Buffer *b = buf;
std::string fname;
if (b) {
fname = b->Filename();
}
if (!fname.empty()) {
try {
fname = std::filesystem::path(fname).filename().string();
} catch (...) {
// keep original on any error
}
} else {
fname = "[no name]";
}
left += " ";
left += fname;
if (b && b->Dirty())
left += " *";
}
// Build left segment
std::string left;
{
const char *app = "kte";
left.reserve(256);
left += app;
left += " ";
left += KTE_VERSION_STR; // already includes leading 'v'
const Buffer *b = buf;
std::string fname;
if (b) {
fname = b->Filename();
}
if (!fname.empty()) {
try {
fname = std::filesystem::path(fname).filename().string();
} catch (...) {
// keep original on any error
}
} else {
fname = "[no name]";
}
left += " ";
left += fname;
if (b && b->Dirty())
left += " *";
}
// Build right segment (cursor and mark)
std::string right;
{
int row1 = 0, col1 = 0;
int mrow1 = 0, mcol1 = 0;
bool have_mark = false;
if (buf) {
row1 = static_cast<int>(buf->Cury()) + 1;
col1 = static_cast<int>(buf->Curx()) + 1;
if (buf->MarkSet()) {
have_mark = true;
mrow1 = static_cast<int>(buf->MarkCury()) + 1;
mcol1 = static_cast<int>(buf->MarkCurx()) + 1;
}
}
char rbuf[128];
if (have_mark)
std::snprintf(rbuf, sizeof(rbuf), "%d,%d | M: %d,%d", row1, col1, mrow1, mcol1);
else
std::snprintf(rbuf, sizeof(rbuf), "%d,%d | M: not set", row1, col1);
right = rbuf;
}
// Build right segment (cursor and mark)
std::string right;
{
int row1 = 0, col1 = 0;
int mrow1 = 0, mcol1 = 0;
bool have_mark = false;
if (buf) {
row1 = static_cast<int>(buf->Cury()) + 1;
col1 = static_cast<int>(buf->Curx()) + 1;
if (buf->MarkSet()) {
have_mark = true;
mrow1 = static_cast<int>(buf->MarkCury()) + 1;
mcol1 = static_cast<int>(buf->MarkCurx()) + 1;
}
}
char rbuf[128];
if (have_mark)
std::snprintf(rbuf, sizeof(rbuf), "%d,%d | M: %d,%d", row1, col1, mrow1, mcol1);
else
std::snprintf(rbuf, sizeof(rbuf), "%d,%d | M: not set", row1, col1);
right = rbuf;
}
// Compute placements with truncation rules: prioritize left and right; middle gets remaining
int rlen = static_cast<int>(right.size());
if (rlen > cols) {
// Hard clip right if too long
right = right.substr(static_cast<std::size_t>(rlen - cols), static_cast<std::size_t>(cols));
rlen = cols;
}
int left_max = std::max(0, cols - rlen - 1); // leave at least 1 space between left and right areas
int llen = static_cast<int>(left.size());
if (llen > left_max) llen = left_max;
// Compute placements with truncation rules: prioritize left and right; middle gets remaining
int rlen = static_cast<int>(right.size());
if (rlen > cols) {
// Hard clip right if too long
right = right.substr(static_cast<std::size_t>(rlen - cols), static_cast<std::size_t>(cols));
rlen = cols;
}
int left_max = std::max(0, cols - rlen - 1); // leave at least 1 space between left and right areas
int llen = static_cast<int>(left.size());
if (llen > left_max)
llen = left_max;
// Draw left
if (llen > 0) mvaddnstr(rows - 1, 0, left.c_str(), llen);
// Draw left
if (llen > 0)
mvaddnstr(rows - 1, 0, left.c_str(), llen);
// Draw right, flush to end
int rstart = std::max(0, cols - rlen);
if (rlen > 0) mvaddnstr(rows - 1, rstart, right.c_str(), rlen);
// Draw right, flush to end
int rstart = std::max(0, cols - rlen);
if (rlen > 0)
mvaddnstr(rows - 1, rstart, right.c_str(), rlen);
// Middle message
const std::string &msg = ed.Status();
if (!msg.empty()) {
int mid_start = llen + 1; // one space after left
int mid_end = rstart - 1; // one space before right
if (mid_end >= mid_start) {
int avail = mid_end - mid_start + 1;
int mlen = static_cast<int>(msg.size());
int mdraw = std::min(avail, mlen);
int mstart = mid_start + std::max(0, (avail - mdraw) / 2); // center within middle area
mvaddnstr(rows - 1, mstart, msg.c_str(), mdraw);
}
}
// Middle message
const std::string &msg = ed.Status();
if (!msg.empty()) {
int mid_start = llen + 1; // one space after left
int mid_end = rstart - 1; // one space before right
if (mid_end >= mid_start) {
int avail = mid_end - mid_start + 1;
int mlen = static_cast<int>(msg.size());
int mdraw = std::min(avail, mlen);
int mstart = mid_start + std::max(0, (avail - mdraw) / 2); // center within middle area
mvaddnstr(rows - 1, mstart, msg.c_str(), mdraw);
}
}
attroff(A_REVERSE);
attroff(A_REVERSE);
// Restore terminal cursor to the content position so a visible caret
// remains in the editing area (not on the status line).
if (saved_cur_y >= 0 && saved_cur_x >= 0) {
move(saved_cur_y, saved_cur_x);
}
// Restore terminal cursor to the content position so a visible caret
// remains in the editing area (not on the status line).
if (saved_cur_y >= 0 && saved_cur_x >= 0) {
move(saved_cur_y, saved_cur_x);
}
refresh();
refresh();
}