Lots of updates:
1. Scrolling and click to set the cursor works. 2. GUI now uses Brass Mono as the font. 3. A lot of stability and other updates.
This commit is contained in:
142
Buffer.cc
Normal file
142
Buffer.cc
Normal file
@@ -0,0 +1,142 @@
|
||||
#include "Buffer.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <filesystem>
|
||||
|
||||
|
||||
Buffer::Buffer() = default;
|
||||
|
||||
|
||||
Buffer::Buffer(const std::string &path)
|
||||
{
|
||||
std::string err;
|
||||
OpenFromFile(path, err);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Buffer::OpenFromFile(const std::string &path, std::string &err)
|
||||
{
|
||||
// If the file doesn't exist, initialize an empty, non-file-backed buffer
|
||||
// with the provided filename. Do not touch the filesystem until Save/SaveAs.
|
||||
if (!std::filesystem::exists(path)) {
|
||||
rows_.clear();
|
||||
nrows_ = 0;
|
||||
filename_ = path;
|
||||
is_file_backed_ = false;
|
||||
dirty_ = false;
|
||||
|
||||
// Reset cursor/viewport state
|
||||
curx_ = cury_ = rx_ = 0;
|
||||
rowoffs_ = coloffs_ = 0;
|
||||
mark_set_ = false;
|
||||
mark_curx_ = mark_cury_ = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::ifstream in(path, std::ios::in | std::ios::binary);
|
||||
if (!in) {
|
||||
err = "Failed to open file: " + path;
|
||||
return false;
|
||||
}
|
||||
|
||||
rows_.clear();
|
||||
std::string line;
|
||||
while (std::getline(in, line)) {
|
||||
// std::getline strips the '\n', keep raw line
|
||||
if (!line.empty() && !in.good()) {
|
||||
// fallthrough
|
||||
}
|
||||
// Handle potential Windows CRLF: strip trailing '\r'
|
||||
if (!line.empty() && line.back() == '\r') {
|
||||
line.pop_back();
|
||||
}
|
||||
rows_.push_back(line);
|
||||
}
|
||||
|
||||
// If file ends with a trailing newline, getline will have produced an empty
|
||||
// last line already. If the file is empty and no lines were read, keep rows_ empty.
|
||||
|
||||
nrows_ = rows_.size();
|
||||
filename_ = path;
|
||||
is_file_backed_ = true;
|
||||
dirty_ = false;
|
||||
|
||||
// Reset cursor/viewport state
|
||||
curx_ = cury_ = rx_ = 0;
|
||||
rowoffs_ = coloffs_ = 0;
|
||||
mark_set_ = false;
|
||||
mark_curx_ = mark_cury_ = 0;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Buffer::Save(std::string &err) const
|
||||
{
|
||||
if (!is_file_backed_ || filename_.empty()) {
|
||||
err = "Buffer is not file-backed; use SaveAs()";
|
||||
return false;
|
||||
}
|
||||
std::ofstream out(filename_, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
if (!out) {
|
||||
err = "Failed to open for write: " + filename_;
|
||||
return false;
|
||||
}
|
||||
for (std::size_t i = 0; i < rows_.size(); ++i) {
|
||||
out.write(rows_[i].data(), static_cast<std::streamsize>(rows_[i].size()));
|
||||
if (i + 1 < rows_.size()) {
|
||||
out.put('\n');
|
||||
}
|
||||
}
|
||||
if (!out.good()) {
|
||||
err = "Write error";
|
||||
return false;
|
||||
}
|
||||
// Note: const method cannot change dirty_. Intentionally const to allow UI code
|
||||
// to decide when to flip dirty flag after successful save.
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
Buffer::SaveAs(const std::string &path, std::string &err)
|
||||
{
|
||||
// Write to the given path
|
||||
std::ofstream out(path, std::ios::out | std::ios::binary | std::ios::trunc);
|
||||
if (!out) {
|
||||
err = "Failed to open for write: " + path;
|
||||
return false;
|
||||
}
|
||||
for (std::size_t i = 0; i < rows_.size(); ++i) {
|
||||
out.write(rows_[i].data(), static_cast<std::streamsize>(rows_[i].size()));
|
||||
if (i + 1 < rows_.size()) {
|
||||
out.put('\n');
|
||||
}
|
||||
}
|
||||
if (!out.good()) {
|
||||
err = "Write error";
|
||||
return false;
|
||||
}
|
||||
|
||||
filename_ = path;
|
||||
is_file_backed_ = true;
|
||||
dirty_ = false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
Buffer::AsString() const
|
||||
{
|
||||
std::stringstream ss;
|
||||
ss << "Buffer<" << this->filename_;
|
||||
if (this->Dirty()) {
|
||||
ss << "*";
|
||||
}
|
||||
ss << ">: " << rows_.size() << " lines";
|
||||
return ss.str();
|
||||
}
|
||||
Reference in New Issue
Block a user