@@ -81,16 +81,19 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
81
81
assert (x >= 0 );
82
82
assert (w <= INT_MAX - x );
83
83
84
+ const char * ptr ;
85
+ int nCols ;
86
+
84
87
// Draw the caption
85
88
const int captionWidth = 3 ;
86
89
const char * caption = Meter_getCaption (this );
87
90
if (w >= captionWidth ) {
88
91
attrset (CRT_colors [METER_TEXT ]);
89
92
90
- const char * ptr = caption ;
91
- int nCols = String_mbswidth (& ptr , 256 , captionWidth );
92
- int len = (int )(ptr - caption );
93
- mvprintw (y , x , "%-*.*s" , len + captionWidth - nCols , len , caption );
93
+ ptr = caption ;
94
+ nCols = String_mbswidth (& ptr , 256 , captionWidth );
95
+ int captionLen = (int )(ptr - caption );
96
+ mvprintw (y , x , "%-*.*s" , captionLen + captionWidth - nCols , captionLen , caption );
94
97
}
95
98
w -= captionWidth ;
96
99
@@ -110,71 +113,94 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
110
113
attrset (CRT_colors [RESET_COLOR ]); // Clear the bold attribute
111
114
x ++ ;
112
115
113
- // The text in the bar is right aligned;
114
- // Pad with maximal spaces and then calculate needed starting position offset
115
- RichString_begin (bar );
116
- RichString_appendChr (& bar , 0 , ' ' , w );
117
- RichString_appendWide (& bar , 0 , this -> txtBuffer );
118
-
119
- int startPos = RichString_sizeVal (bar ) - w ;
120
- if (startPos > w ) {
121
- // Text is too large for bar
122
- // Truncate meter text at a space character
123
- for (int pos = 2 * w ; pos > w ; pos -- ) {
124
- if (RichString_getCharVal (bar , pos ) == ' ' ) {
125
- while (pos > w && RichString_getCharVal (bar , pos - 1 ) == ' ' )
126
- pos -- ;
127
- startPos = pos - w ;
128
- break ;
129
- }
130
- }
116
+ // Calculate the number of terminal columns needed for the meter text.
131
117
132
- // If still too large, print the start not the end
133
- startPos = MINIMUM (startPos , w );
134
- }
118
+ // The text in the bar is right aligned
135
119
136
- assert ( startPos >= 0 ) ;
137
- assert ( startPos <= w );
138
- assert ( startPos + w <= RichString_sizeVal ( bar ) );
120
+ ptr = this -> txtBuffer ;
121
+ nCols = String_lineBreakWidth ( & ptr , sizeof ( this -> txtBuffer ) - 1 , w , ' ' );
122
+ size_t len = ( size_t )( ptr - this -> txtBuffer );
139
123
140
- int blockSizes [10 ];
124
+ RichString_begin (bar );
125
+ RichString_appendChr (& bar , 0 , ' ' , w - nCols );
126
+ RichString_appendnWide (& bar , 0 , this -> txtBuffer , len );
141
127
142
- // First draw in the bar[] buffer...
128
+ size_t charPos = 0 ;
143
129
int offset = 0 ;
144
130
for (uint8_t i = 0 ; i < this -> curItems ; i ++ ) {
131
+ if (!(this -> total > 0.0 )) {
132
+ break ;
133
+ }
134
+ if (offset >= w ) {
135
+ break ;
136
+ }
137
+
145
138
double value = this -> values [i ];
146
- if (isPositive (value ) && this -> total > 0.0 ) {
147
- value = MINIMUM (value , this -> total );
148
- blockSizes [i ] = ceil ((value / this -> total ) * w );
149
- blockSizes [i ] = MINIMUM (blockSizes [i ], w - offset );
150
- } else {
151
- blockSizes [i ] = 0 ;
139
+ if (!isPositive (value )) {
140
+ continue ;
141
+ }
142
+ value = MINIMUM (value , this -> total );
143
+ int blockSize = ceil ((value / this -> total ) * w );
144
+ blockSize = MINIMUM (blockSize , w - offset );
145
+ if (blockSize < 1 ) {
146
+ continue ;
152
147
}
153
- int nextOffset = offset + blockSizes [i ];
154
- for (int j = offset ; j < nextOffset ; j ++ )
155
- if (RichString_getCharVal (bar , startPos + j ) == ' ' ) {
148
+
149
+ int nextOffset = offset + blockSize ;
150
+ assert (offset < nextOffset );
151
+
152
+ size_t startPos = charPos ;
153
+ while (true) {
154
+ if (offset >= nextOffset ) {
155
+ #ifdef HAVE_LIBNCURSESW
156
+ if (!CRT_utf8 ) {
157
+ break ;
158
+ }
159
+ #else
160
+ break ;
161
+ #endif
162
+ }
163
+
164
+ #ifdef HAVE_LIBNCURSESW
165
+ wchar_t ch = RichString_getCharVal (bar , charPos );
166
+ if (ch == 0 )
167
+ break ;
168
+
169
+ nCols = wcwidth (ch );
170
+ assert (nCols >= 0 );
171
+
172
+ if (offset >= nextOffset && nCols > 0 ) {
173
+ // This break condition is for UTF-8.
174
+ break ;
175
+ }
176
+ #else
177
+ char ch = RichString_getCharVal (bar , charPos );
178
+ nCols = 1 ;
179
+
180
+ assert (offset < nextOffset );
181
+ #endif
182
+ if (ch == ' ' ) {
156
183
if (CRT_colorScheme == COLORSCHEME_MONOCHROME ) {
157
184
assert (i < strlen (BarMeterMode_characters ));
158
- RichString_setChar (& bar , startPos + j , BarMeterMode_characters [i ]);
185
+ RichString_setChar (& bar , charPos , BarMeterMode_characters [i ]);
159
186
} else {
160
- RichString_setChar (& bar , startPos + j , '|' );
187
+ RichString_setChar (& bar , charPos , '|' );
161
188
}
162
189
}
163
- offset = nextOffset ;
164
- }
165
190
166
- // ...then print the buffer.
167
- offset = 0 ;
168
- for (uint8_t i = 0 ; i < this -> curItems ; i ++ ) {
191
+ offset += nCols ;
192
+ charPos ++ ;
193
+ }
194
+
169
195
int attr = this -> curAttributes ? this -> curAttributes [i ] : Meter_attributes (this )[i ];
170
- RichString_setAttrn (& bar , CRT_colors [attr ], startPos + offset , blockSizes [i ]);
171
- RichString_printoffnVal (bar , y , x + offset , startPos + offset , blockSizes [i ]);
172
- offset += blockSizes [i ];
196
+ RichString_setAttrn (& bar , CRT_colors [attr ], startPos , charPos - startPos );
173
197
}
174
- if (offset < w ) {
175
- RichString_setAttrn (& bar , CRT_colors [BAR_SHADOW ], startPos + offset , w - offset );
176
- RichString_printoffnVal (bar , y , x + offset , startPos + offset , w - offset );
198
+
199
+ len = RichString_sizeVal (bar );
200
+ if (charPos < len ) {
201
+ RichString_setAttrn (& bar , CRT_colors [BAR_SHADOW ], charPos , len - charPos );
177
202
}
203
+ RichString_printVal (bar , y , x );
178
204
179
205
RichString_delete (& bar );
180
206
0 commit comments