You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

198 lines
8.4 KiB

#include "TextBlock.h"
#include <iostream>
void TextBlock::print() {
std::cout << "TextBlock::print - " << this->lines.size() << std::endl;
for(auto line: this->lines) {
std::cout << "[" << line << "]" << std::endl;
}
std::cout << "TextBlock::print - trailingNewline " << this->trailingNewline << std::endl;
}
// only safe to one char rn
void TextBlock::insertAt(std::string str, size_t x, size_t y) {
if (y > this->lines.size()) {
std::cout << "TextArea::insertCharAt - y: " << y << " lines: " << this->lines.size() << std::endl;
return;
}
if (!this->lines.size()) {
this->lines.push_back(str);
return;
}
if (x > this->lines[y].size()) {
this->lines[y] += str;
return;
}
// FIXME: search entire str for any \r
if (str == "\r") {
this->lines.push_back("");
// does this mean we need to insert one
// or that we have one?
// what problem was it originally trying to solve?
//this->trailingNewline = true;
// not sure what up's with this shit but it breaks a lot...
//this->setValue(this->getValue()); // in-efficient but should give a correctish algorithm
} else {
//std::cout << "TextBlock::insertAt - [" << this->lines[y].substr(0, x) << "]+[" << str << "]+[" << this->lines[y].substr(x) << "]" << std::endl;
this->lines[y] = this->lines[y].substr(0, x) + str + this->lines[y].substr(x);
}
//std::cout << "TextBlock::insertAt - lines: " << this->lines.size() << std::endl;
}
// only tested to one char atm
void TextBlock::deleteAt(size_t x, size_t y, size_t count) {
//std::cout << "TextBlock::deleteAt - start delete " << count << " chars @ " << x << "," << y << std::endl;
if (y > this->lines.size()) {
std::cout << "TextArea::deleteAt - y: " << y << " lines: " << this->lines.size() << std::endl;
return;
}
// could we just remove the if?
if (count) {
if (x == 0) {
if (y) {
//std::cout << "TextArea::deleteAt - y!=0, lines: " << this->lines.size() << std::endl;
if (y < this->lines.size()) {
//std::cout << "TextArea::deleteAt - nuked line [" << y << "] chars on line: " << this->lineLength(y) << std::endl;
if (this->lineLength(y)) {
this->trailingNewline = true;
}
this->lines.erase(this->lines.begin() + static_cast<int>(y));
return;
} else {
if (y == this->lines.size()) {
// delete the last line
if (this->trailingNewline) {
this->trailingNewline = false;
} else {
std::cout << "TextArea::deleteAt - do nothing" << std::endl;
}
return;
}
std::cout << "TextArea::deleteAt - requesting deletion at " << x << "," << y << " but only " << this->lines.size() << std::endl;
}
} // else we're at 0,0 deleting a char
}
if (x >= this->lineLength(y)) {
//std::cout << "TextArea::deleteAt - x == lineLength [" << this->lines[y].substr(0, x - 1) << "]" << std::endl;
if (x) {
this->lines[y] = this->lines[y].substr(0, x - 1);
} else {
this->trailingNewline = false;
}
} else {
if (x) {
if (x == this->lineLength(y) - 1) {
//std::cout << "TextArea::deleteAt - endOfLine [" << this->lines[y].substr(0, x) << "]+[" << this->lines[y].substr(x + count) << "]" << std::endl;
this->lines[y] = this->lines[y].substr(0, x) + this->lines[y].substr(x + count);
} else {
//std::cout << "TextArea::deleteAt - x>0 [" << this->lines[y].substr(0, x) << "]+[" << this->lines[y].substr(x + count) << "]" << std::endl;
this->lines[y] = this->lines[y].substr(0, x) + this->lines[y].substr(x + count);
}
} else {
//std::cout << "TextArea::deleteAt - x@0 [" << this->lines[y].substr(x + count) << "]" << std::endl;
this->lines[y] = this->lines[y].substr(x + count);
}
}
} else {
this->lines[y] = this->lines[y].substr(0, x);
}
}
size_t TextBlock::setValue(std::string value) {
// split on \n
std::string delimiter(1, '\r');
this->lines.clear();
size_t pos = 0;
size_t lPos = 0;
size_t tLines = 0; // start at 0 (should this start at 1?)
this->trailingNewline = false;
while ((pos = value.find(delimiter, lPos)) != std::string::npos) {
//std::cout << "TextBlock::setValue pushing [" << value.substr(lPos, pos) << "]" << std::endl;
std::string token = value.substr(lPos, pos);
if (token[token.size() - 1] == '\r') {
token.pop_back();
//std::cout << "TextBlock::setValue adjusted [" << token << "]" << std::endl;
//std::cout << "lPos: " << lPos << " pos: " << pos << " size: " << value.size() << std::endl;
if (pos == value.size() - 1) {
//std::cout << "TextBlock::setValue - enabling trailing line" << std::endl;
this->trailingNewline = true;
}
}
this->lines.push_back(token);
//value.erase(0, pos + delimiter.length());
lPos = pos + delimiter.length();
tLines++;
}
//std::cout << "lPos: " << lPos << " pos: " << pos << " size: " << value.size() << " last: [" << value.substr(lPos) << "]" << std::endl;
// if we're not at the end of the string, we don't end on a trailing slash
// lPos == value.size()? true :
if (value.substr(lPos) != "") {
//std::cout << "Pushing back [" << value.substr(lPos) << "]" << std::endl;
this->lines.push_back(value.substr(lPos));
} else {
if (lPos == 1) {
this->trailingNewline = true;
}
}
return tLines;
}
std::string TextBlock::getValue() {
std::string value = "";
for(auto s : this->lines) {
value += s + '\r';
}
//std::cout << "TextBlock::getValue before strip[" << !this->trailingNewline << "] [" << value << "] lines[" << this->lines.size() << "]" << std::endl;
if (!this->trailingNewline && this->lines.size()) {
value.pop_back();
}
return value;
}
std::string TextBlock::getValueUpTo(size_t x, size_t y) {
std::string value;
if (y && this->lines.size()) {
for(size_t cy = 0; cy < y; cy++) {
value += this->lines[cy] + "\r";
}
// we don't want this because 1st char on the 2nd line breaks
/*
// if we're not at the start of a new line, remove the newline
if (this->lineLength(y)) {
std::cout << "TextBlock::getValueUpTo - removing added newline because this line has text" << std::endl;
value.pop_back();
}
*/
//std::cout << "TextBlock::getValueUpTo y read[" << value << "]" << std::endl;
}
if (x) {
//std::cout << "TextBlock::getValueUpTo value pre x [" << value << "]" << std::endl;
value += this->lines[y].substr(0, x);
//std::cout << "TextBlock::getValueUpTo x [" << value << "]" << std::endl;
}
//std::cout << "TextBlock::getValueUpTo trailingNewline: " << this->trailingNewline << std::endl;
/*
if (this->trailingNewline) {
// and we're at the end of the last line
//std::cout << "lines: " << this->lines.size() << " lineLength: " << this->lineLength(y) << std::endl;
// x can't be at the start of the line
//if (y == this->lines.size() - 1 && x == this->lineLength(y) && x) {
//std::cout << "TextBlock::getValueUpTo adding a trailingNewline" << std::endl;
//value += "\r";
//}
}
*/
return value;
}
size_t TextBlock::lineLength(size_t y) {
if (y >= this->lines.size()) {
if (!this->trailingNewline) {
std::cout << "TextArea::lengthLine - y: " << y << " lines: " << this->lines.size() << std::endl;
}
return 0;
}
return this->lines[y].size();
}