- Add visual file picker for GUI with toggle support. - Introduce `GUIConfig` class for loading GUI settings from configuration file. - Refactor window initialization to support dynamic sizing based on configuration. - Add macOS-specific handling for fullscreen behavior. - Improve header inclusion order and minor code cleanup.
205 lines
3.3 KiB
C++
205 lines
3.3 KiB
C++
#include <algorithm>
|
|
#include <cassert>
|
|
#include <cstring>
|
|
|
|
#include "GapBuffer.h"
|
|
|
|
|
|
GapBuffer::GapBuffer() = default;
|
|
|
|
|
|
GapBuffer::GapBuffer(std::size_t initialCapacity)
|
|
: buffer_(nullptr), size_(0), capacity_(0)
|
|
{
|
|
if (initialCapacity > 0) {
|
|
Reserve(initialCapacity);
|
|
}
|
|
}
|
|
|
|
|
|
GapBuffer::GapBuffer(const GapBuffer &other)
|
|
: buffer_(nullptr), size_(0), capacity_(0)
|
|
{
|
|
if (other.capacity_ > 0) {
|
|
Reserve(other.capacity_);
|
|
if (other.size_ > 0) {
|
|
std::memcpy(buffer_, other.buffer_, other.size_);
|
|
size_ = other.size_;
|
|
}
|
|
setTerminator();
|
|
}
|
|
}
|
|
|
|
|
|
GapBuffer &
|
|
GapBuffer::operator=(const GapBuffer &other)
|
|
{
|
|
if (this == &other)
|
|
return *this;
|
|
if (other.capacity_ > capacity_) {
|
|
Reserve(other.capacity_);
|
|
}
|
|
if (other.size_ > 0) {
|
|
std::memcpy(buffer_, other.buffer_, other.size_);
|
|
}
|
|
size_ = other.size_;
|
|
setTerminator();
|
|
return *this;
|
|
}
|
|
|
|
|
|
GapBuffer::GapBuffer(GapBuffer &&other) noexcept
|
|
: buffer_(other.buffer_), size_(other.size_), capacity_(other.capacity_)
|
|
{
|
|
other.buffer_ = nullptr;
|
|
other.size_ = 0;
|
|
other.capacity_ = 0;
|
|
}
|
|
|
|
|
|
GapBuffer &
|
|
GapBuffer::operator=(GapBuffer &&other) noexcept
|
|
{
|
|
if (this == &other)
|
|
return *this;
|
|
delete[] buffer_;
|
|
buffer_ = other.buffer_;
|
|
size_ = other.size_;
|
|
capacity_ = other.capacity_;
|
|
other.buffer_ = nullptr;
|
|
other.size_ = 0;
|
|
other.capacity_ = 0;
|
|
return *this;
|
|
}
|
|
|
|
|
|
GapBuffer::~GapBuffer()
|
|
{
|
|
delete[] buffer_;
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::Reserve(const std::size_t newCapacity)
|
|
{
|
|
if (newCapacity <= capacity_)
|
|
return;
|
|
// Allocate space for terminator as well
|
|
char *nb = new char[newCapacity + 1];
|
|
if (size_ > 0 && buffer_) {
|
|
std::memcpy(nb, buffer_, size_);
|
|
}
|
|
delete[] buffer_;
|
|
buffer_ = nb;
|
|
capacity_ = newCapacity;
|
|
setTerminator();
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::AppendChar(const char c)
|
|
{
|
|
ensureCapacityFor(1);
|
|
buffer_[size_++] = c;
|
|
setTerminator();
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::Append(const char *s, const std::size_t len)
|
|
{
|
|
if (!s || len == 0)
|
|
return;
|
|
ensureCapacityFor(len);
|
|
std::memcpy(buffer_ + size_, s, len);
|
|
size_ += len;
|
|
setTerminator();
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::Append(const GapBuffer &other)
|
|
{
|
|
if (other.size_ == 0)
|
|
return;
|
|
Append(other.buffer_, other.size_);
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::PrependChar(char c)
|
|
{
|
|
ensureCapacityFor(1);
|
|
// shift right by 1
|
|
if (size_ > 0) {
|
|
std::memmove(buffer_ + 1, buffer_, size_);
|
|
}
|
|
buffer_[0] = c;
|
|
++size_;
|
|
setTerminator();
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::Prepend(const char *s, std::size_t len)
|
|
{
|
|
if (!s || len == 0)
|
|
return;
|
|
ensureCapacityFor(len);
|
|
if (size_ > 0) {
|
|
std::memmove(buffer_ + len, buffer_, size_);
|
|
}
|
|
std::memcpy(buffer_, s, len);
|
|
size_ += len;
|
|
setTerminator();
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::Prepend(const GapBuffer &other)
|
|
{
|
|
if (other.size_ == 0)
|
|
return;
|
|
Prepend(other.buffer_, other.size_);
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::Clear()
|
|
{
|
|
size_ = 0;
|
|
setTerminator();
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::ensureCapacityFor(std::size_t delta)
|
|
{
|
|
if (capacity_ - size_ >= delta)
|
|
return;
|
|
auto required = size_ + delta;
|
|
Reserve(growCapacity(capacity_, required));
|
|
}
|
|
|
|
|
|
std::size_t
|
|
GapBuffer::growCapacity(std::size_t current, std::size_t required)
|
|
{
|
|
// geometric growth, at least required
|
|
std::size_t newCap = current ? current : 8;
|
|
while (newCap < required)
|
|
newCap = newCap + (newCap >> 1); // 1.5x growth
|
|
return newCap;
|
|
}
|
|
|
|
|
|
void
|
|
GapBuffer::setTerminator() const
|
|
{
|
|
if (!buffer_) {
|
|
return;
|
|
}
|
|
|
|
buffer_[size_] = '\0';
|
|
}
|