--- 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;