Files
kte/UndoSystem.cc
Kyle Isom cbbde43dc2 Stub out previous undo implementation; update docs.
- Remove outdated `undo-state.md`
- Add two code quality/optimization reports that were used to guide previous work:
  - `code-report.md` (optimization)
  - `code-report-quality.md` (stability and code health)
- Add `themes.md`.
- Update undo system docs and roadmap.
2025-12-03 15:12:28 -08:00

250 lines
4.7 KiB
C++

#include "UndoSystem.h"
#include "Buffer.h"
#include <cassert>
#include <cstdio>
UndoSystem::UndoSystem(Buffer &owner, UndoTree &tree)
: buf_(&owner), tree_(tree) {}
void
UndoSystem::Begin(UndoType type)
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
(void) type;
}
void
UndoSystem::Append(char ch)
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
(void) ch;
}
void
UndoSystem::Append(std::string_view text)
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
(void) text;
}
void
UndoSystem::commit()
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
}
void
UndoSystem::undo()
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
}
void
UndoSystem::redo()
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
}
void
UndoSystem::mark_saved()
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
}
void
UndoSystem::discard_pending()
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
}
void
UndoSystem::clear()
{
// STUB: Undo system incomplete - disabled until it can be properly implemented
}
void
UndoSystem::apply(const UndoNode *node, int direction)
{
if (!node)
return;
switch (node->type) {
case UndoType::Insert:
case UndoType::Paste:
if (direction > 0) {
buf_->insert_text(node->row, node->col, node->text);
} else {
buf_->delete_text(node->row, node->col, node->text.size());
}
break;
case UndoType::Delete:
if (direction > 0) {
buf_->delete_text(node->row, node->col, node->text.size());
} else {
buf_->insert_text(node->row, node->col, node->text);
}
break;
case UndoType::Newline:
if (direction > 0) {
buf_->split_line(node->row, node->col);
} else {
buf_->join_lines(node->row);
}
break;
case UndoType::DeleteRow:
if (direction > 0) {
buf_->delete_row(node->row);
} else {
buf_->insert_row(node->row, node->text);
}
break;
}
}
void
UndoSystem::free_node(UndoNode *node)
{
if (!node)
return;
// Free child subtree(s) and sibling branches
if (node->child) {
// Free entire redo list starting at child, including each subtree
UndoNode *branch = node->child;
while (branch) {
UndoNode *next = branch->next;
free_node(branch);
branch = next;
}
node->child = nullptr;
}
delete node;
}
void
UndoSystem::free_branch(UndoNode *node)
{
// Free a branch list (node and its next siblings) including their subtrees
while (node) {
UndoNode *next = node->next;
free_node(node);
node = next;
}
}
static bool
dfs_find_parent(UndoNode *cur, UndoNode *target, UndoNode *&out_parent)
{
if (!cur)
return false;
for (UndoNode *child = cur->child; child != nullptr; child = child->next) {
if (child == target) {
out_parent = cur;
return true;
}
if (dfs_find_parent(child, target, out_parent))
return true;
}
return false;
}
UndoNode *
UndoSystem::find_parent(UndoNode *from, UndoNode *target)
{
if (!from || !target)
return nullptr;
if (from == target)
return nullptr;
UndoNode *parent = nullptr;
dfs_find_parent(from, target, parent);
return parent;
}
void
UndoSystem::update_dirty_flag()
{
// dirty if current != saved
bool dirty = (tree_.current != tree_.saved);
buf_->SetDirty(dirty);
}
void
UndoSystem::UpdateBufferReference(Buffer &new_buf)
{
buf_ = &new_buf;
}
// ---- Debug helpers ----
const char *
UndoSystem::type_str(UndoType t)
{
switch (t) {
case UndoType::Insert:
return "Insert";
case UndoType::Delete:
return "Delete";
case UndoType::Paste:
return "Paste";
case UndoType::Newline:
return "Newline";
case UndoType::DeleteRow:
return "DeleteRow";
}
return "?";
}
bool
UndoSystem::is_descendant(UndoNode *root, const UndoNode *target)
{
if (!root || !target)
return false;
if (root == target)
return true;
for (UndoNode *child = root->child; child != nullptr; child = child->next) {
if (is_descendant(child, target))
return true;
}
return false;
}
void
UndoSystem::debug_log(const char *op) const
{
#ifdef KTE_UNDO_DEBUG
int row = static_cast<int>(buf_->Cury());
int col = static_cast<int>(buf_->Curx());
const UndoNode *p = tree_.pending;
std::fprintf(stderr,
"[UNDO] %s cur=(%d,%d) pending=%p t=%s r=%d c=%d nlen=%zu current=%p saved=%p\n",
op,
row, col,
(const void *) p,
p ? type_str(p->type) : "-",
p ? p->row : -1,
p ? p->col : -1,
p ? p->text.size() : 0,
(void *) tree_.current,
(void *) tree_.saved);
#else
(void) op;
#endif
}