@@ -90,16 +90,19 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
9090 assert (x >= 0 );
9191 assert (w <= INT_MAX - x );
9292
93+ const char * ptr ;
94+ int nCols ;
95+
9396 // Draw the caption
9497 const int captionWidth = 3 ;
9598 const char * caption = Meter_getCaption (this );
9699 if (w >= captionWidth ) {
97100 attrset (CRT_colors [METER_TEXT ]);
98101
99- const char * ptr = caption ;
100- int nCols = String_mbswidth (& ptr , 256 , captionWidth );
101- int len = (int )(ptr - caption );
102- mvprintw (y , x , "%-*.*s" , len + captionWidth - nCols , len , caption );
102+ ptr = caption ;
103+ nCols = String_mbswidth (& ptr , 256 , captionWidth );
104+ int captionLen = (int )(ptr - caption );
105+ mvprintw (y , x , "%-*.*s" , captionLen + captionWidth - nCols , captionLen , caption );
103106 }
104107 w -= captionWidth ;
105108
@@ -125,71 +128,94 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
125128 attrset (CRT_colors [RESET_COLOR ]); // Clear the bold attribute
126129 x ++ ;
127130
128- // The text in the bar is right aligned;
129- // Pad with maximal spaces and then calculate needed starting position offset
130- RichString_begin (bar );
131- RichString_appendChr (& bar , 0 , ' ' , w );
132- RichString_appendWide (& bar , 0 , this -> txtBuffer );
133-
134- int startPos = RichString_sizeVal (bar ) - w ;
135- if (startPos > w ) {
136- // Text is too large for bar
137- // Truncate meter text at a space character
138- for (int pos = 2 * w ; pos > w ; pos -- ) {
139- if (RichString_getCharVal (bar , pos ) == ' ' ) {
140- while (pos > w && RichString_getCharVal (bar , pos - 1 ) == ' ' )
141- pos -- ;
142- startPos = pos - w ;
143- break ;
144- }
145- }
131+ // Calculate the number of terminal columns needed for the meter text.
146132
147- // If still too large, print the start not the end
148- startPos = MINIMUM (startPos , w );
149- }
133+ // The text in the bar is right aligned
150134
151- assert ( startPos >= 0 ) ;
152- assert ( startPos <= w );
153- assert ( startPos + w <= RichString_sizeVal ( bar ) );
135+ ptr = this -> txtBuffer ;
136+ nCols = String_lineBreakWidth ( & ptr , sizeof ( this -> txtBuffer ) - 1 , w , ' ' );
137+ size_t len = ( size_t )( ptr - this -> txtBuffer );
154138
155- int blockSizes [10 ];
139+ RichString_begin (bar );
140+ RichString_appendChr (& bar , 0 , ' ' , w - nCols );
141+ RichString_appendnWide (& bar , 0 , this -> txtBuffer , len );
156142
157- // First draw in the bar[] buffer...
143+ size_t charPos = 0 ;
158144 int offset = 0 ;
159145 for (uint8_t i = 0 ; i < this -> curItems ; i ++ ) {
146+ if (!(this -> total > 0.0 )) {
147+ break ;
148+ }
149+ if (offset >= w ) {
150+ break ;
151+ }
152+
160153 double value = this -> values [i ];
161- if (isPositive (value ) && this -> total > 0.0 ) {
162- value = MINIMUM (value , this -> total );
163- blockSizes [i ] = ceil ((value / this -> total ) * w );
164- blockSizes [i ] = MINIMUM (blockSizes [i ], w - offset );
165- } else {
166- blockSizes [i ] = 0 ;
154+ if (!isPositive (value )) {
155+ continue ;
156+ }
157+ value = MINIMUM (value , this -> total );
158+ int blockSize = ceil ((value / this -> total ) * w );
159+ blockSize = MINIMUM (blockSize , w - offset );
160+ if (blockSize < 1 ) {
161+ continue ;
167162 }
168- int nextOffset = offset + blockSizes [i ];
169- for (int j = offset ; j < nextOffset ; j ++ )
170- if (RichString_getCharVal (bar , startPos + j ) == ' ' ) {
163+
164+ int nextOffset = offset + blockSize ;
165+ assert (offset < nextOffset );
166+
167+ size_t startPos = charPos ;
168+ while (true) {
169+ if (offset >= nextOffset ) {
170+ #ifdef HAVE_LIBNCURSESW
171+ if (!CRT_utf8 ) {
172+ break ;
173+ }
174+ #else
175+ break ;
176+ #endif
177+ }
178+
179+ #ifdef HAVE_LIBNCURSESW
180+ wchar_t ch = RichString_getCharVal (bar , charPos );
181+ if (ch == 0 )
182+ break ;
183+
184+ nCols = wcwidth (ch );
185+ assert (nCols >= 0 );
186+
187+ if (offset >= nextOffset && nCols > 0 ) {
188+ // This break condition is for UTF-8.
189+ break ;
190+ }
191+ #else
192+ char ch = RichString_getCharVal (bar , charPos );
193+ nCols = 1 ;
194+
195+ assert (offset < nextOffset );
196+ #endif
197+ if (ch == ' ' ) {
171198 if (CRT_colorScheme == COLORSCHEME_MONOCHROME ) {
172199 assert (i < strlen (BarMeterMode_characters ));
173- RichString_setChar (& bar , startPos + j , BarMeterMode_characters [i ]);
200+ RichString_setChar (& bar , charPos , BarMeterMode_characters [i ]);
174201 } else {
175- RichString_setChar (& bar , startPos + j , '|' );
202+ RichString_setChar (& bar , charPos , '|' );
176203 }
177204 }
178- offset = nextOffset ;
179- }
180205
181- // ...then print the buffer.
182- offset = 0 ;
183- for (uint8_t i = 0 ; i < this -> curItems ; i ++ ) {
206+ offset += nCols ;
207+ charPos ++ ;
208+ }
209+
184210 int attr = this -> curAttributes ? this -> curAttributes [i ] : Meter_attributes (this )[i ];
185- RichString_setAttrn (& bar , CRT_colors [attr ], startPos + offset , blockSizes [i ]);
186- RichString_printoffnVal (bar , y , x + offset , startPos + offset , blockSizes [i ]);
187- offset += blockSizes [i ];
211+ RichString_setAttrn (& bar , CRT_colors [attr ], startPos , charPos - startPos );
188212 }
189- if (offset < w ) {
190- RichString_setAttrn (& bar , CRT_colors [BAR_SHADOW ], startPos + offset , w - offset );
191- RichString_printoffnVal (bar , y , x + offset , startPos + offset , w - offset );
213+
214+ len = RichString_sizeVal (bar );
215+ if (charPos < len ) {
216+ RichString_setAttrn (& bar , CRT_colors [BAR_SHADOW ], charPos , len - charPos );
192217 }
218+ RichString_printVal (bar , y , x );
193219
194220 RichString_delete (& bar );
195221
0 commit comments