# HG changeset patch # User František Kučera # Date 1676769983 -3600 # Node ID 002077ecb17a03d8813bb48ab6f55870e771f8d7 # Parent f67047a1e19e6bf08f5f154fcb2e7c0c9aa915dc long line wrapping: first version diff -r f67047a1e19e -r 002077ecb17a src/RecfileHandler.h --- a/src/RecfileHandler.h Sun Feb 19 00:36:47 2023 +0100 +++ b/src/RecfileHandler.h Sun Feb 19 02:26:23 2023 +0100 @@ -111,12 +111,64 @@ return escaped.str(); } + integer_t computeWidth(const wchar_t ch) { + switch (ch) { + case L'\t': + // TODO: tabulator width? + return 4; + case L' ': + return 1; + default: + return std::max(0, wcwidth(ch)); + } + } + + /** + * @param stringValue + * @return the width that would the string occupy on the display (particular characters might be wider than 1 column) + */ + integer_t computeWidth(const string_t & stringValue) { + integer_t width = 0; + for (wchar_t ch : stringValue) width += computeWidth(ch); + return width; + } + void writeAttribute(const string_t& escapedName, const TypeId& type, const string_t& value) { output << convertor.to_bytes(escapedName) << ": "; - for (char ch : convertor.to_bytes(value)) { - output << ch; - if (ch == '\n') output << "+ "; + static const integer_t MAX_LINE_WIDTH = 80; // TODO: configuration + static const boolean_t unlimited = MAX_LINE_WIDTH == -1; + + integer_t currentWidth = computeWidth(escapedName) + 2; // 2 = ": " separator + integer_t valueWidth = computeWidth(value); + integer_t remainingWidth = valueWidth; + + + for (size_t i = 0, limit = value.size(); i < limit; i++) { + wchar_t ch = value[i]; + integer_t characterWidth = computeWidth(ch); + + if (ch == '\n') { + output << std::endl << "+ "; + currentWidth = 2; // 2 = "+ " prefix + } else { + if (unlimited || (currentWidth + remainingWidth) <= MAX_LINE_WIDTH) { + // all remaining characters fit the in the limit + currentWidth += characterWidth; + output << convertor.to_bytes(ch); + } else if ((currentWidth + characterWidth + 1) <= MAX_LINE_WIDTH) { // 1 = "\" + // we will wrap the line, but not yet + currentWidth += characterWidth; + output << convertor.to_bytes(ch); + } else { + output << "\\" << std::endl; + currentWidth = 0; + currentWidth += characterWidth; + output << convertor.to_bytes(ch); + } + } + + remainingWidth -= characterWidth; } output << std::endl;