109 } |
109 } |
110 |
110 |
111 return escaped.str(); |
111 return escaped.str(); |
112 } |
112 } |
113 |
113 |
|
114 integer_t computeWidth(const wchar_t ch) { |
|
115 switch (ch) { |
|
116 case L'\t': |
|
117 // TODO: tabulator width? |
|
118 return 4; |
|
119 case L' ': |
|
120 return 1; |
|
121 default: |
|
122 return std::max(0, wcwidth(ch)); |
|
123 } |
|
124 } |
|
125 |
|
126 /** |
|
127 * @param stringValue |
|
128 * @return the width that would the string occupy on the display (particular characters might be wider than 1 column) |
|
129 */ |
|
130 integer_t computeWidth(const string_t & stringValue) { |
|
131 integer_t width = 0; |
|
132 for (wchar_t ch : stringValue) width += computeWidth(ch); |
|
133 return width; |
|
134 } |
|
135 |
114 void writeAttribute(const string_t& escapedName, const TypeId& type, const string_t& value) { |
136 void writeAttribute(const string_t& escapedName, const TypeId& type, const string_t& value) { |
115 output << convertor.to_bytes(escapedName) << ": "; |
137 output << convertor.to_bytes(escapedName) << ": "; |
116 |
138 |
117 for (char ch : convertor.to_bytes(value)) { |
139 static const integer_t MAX_LINE_WIDTH = 80; // TODO: configuration |
118 output << ch; |
140 static const boolean_t unlimited = MAX_LINE_WIDTH == -1; |
119 if (ch == '\n') output << "+ "; |
141 |
|
142 integer_t currentWidth = computeWidth(escapedName) + 2; // 2 = ": " separator |
|
143 integer_t valueWidth = computeWidth(value); |
|
144 integer_t remainingWidth = valueWidth; |
|
145 |
|
146 |
|
147 for (size_t i = 0, limit = value.size(); i < limit; i++) { |
|
148 wchar_t ch = value[i]; |
|
149 integer_t characterWidth = computeWidth(ch); |
|
150 |
|
151 if (ch == '\n') { |
|
152 output << std::endl << "+ "; |
|
153 currentWidth = 2; // 2 = "+ " prefix |
|
154 } else { |
|
155 if (unlimited || (currentWidth + remainingWidth) <= MAX_LINE_WIDTH) { |
|
156 // all remaining characters fit the in the limit |
|
157 currentWidth += characterWidth; |
|
158 output << convertor.to_bytes(ch); |
|
159 } else if ((currentWidth + characterWidth + 1) <= MAX_LINE_WIDTH) { // 1 = "\" |
|
160 // we will wrap the line, but not yet |
|
161 currentWidth += characterWidth; |
|
162 output << convertor.to_bytes(ch); |
|
163 } else { |
|
164 output << "\\" << std::endl; |
|
165 currentWidth = 0; |
|
166 currentWidth += characterWidth; |
|
167 output << convertor.to_bytes(ch); |
|
168 } |
|
169 } |
|
170 |
|
171 remainingWidth -= characterWidth; |
120 } |
172 } |
121 |
173 |
122 output << std::endl; |
174 output << std::endl; |
123 } |
175 } |
124 |
176 |