@@ -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,90 @@ 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+ if (offset >= w )
149+ break ;
150+
160151 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 ;
167- }
168- int nextOffset = offset + blockSizes [i ];
169- for (int j = offset ; j < nextOffset ; j ++ )
170- if (RichString_getCharVal (bar , startPos + j ) == ' ' ) {
152+ if (!isPositive (value ))
153+ continue ;
154+ value = MINIMUM (value , this -> total );
155+ int blockSize = ceil ((value / this -> total ) * w );
156+ blockSize = MINIMUM (blockSize , w - offset );
157+ if (blockSize < 1 )
158+ continue ;
159+
160+ int nextOffset = offset + blockSize ;
161+ assert (offset < nextOffset );
162+
163+ size_t startPos = charPos ;
164+ while (true) {
165+ #ifdef HAVE_LIBNCURSESW
166+ if (offset >= nextOffset && !CRT_utf8 ) {
167+ break ;
168+ }
169+ #else
170+ if (offset >= nextOffset ) {
171+ break ;
172+ }
173+ #endif
174+
175+ #ifdef HAVE_LIBNCURSESW
176+ wchar_t ch = RichString_getCharVal (bar , charPos );
177+ if (ch == 0 )
178+ break ;
179+
180+ nCols = wcwidth (ch );
181+ assert (nCols >= 0 );
182+
183+ if (offset >= nextOffset && nCols > 0 ) {
184+ // This break condition is for UTF-8.
185+ break ;
186+ }
187+ #else
188+ char ch = RichString_getCharVal (bar , charPos );
189+ nCols = 1 ;
190+
191+ assert (offset < nextOffset );
192+ #endif
193+ if (ch == ' ' ) {
171194 if (CRT_colorScheme == COLORSCHEME_MONOCHROME ) {
172195 assert (i < strlen (BarMeterMode_characters ));
173- RichString_setChar (& bar , startPos + j , BarMeterMode_characters [i ]);
196+ RichString_setChar (& bar , charPos , BarMeterMode_characters [i ]);
174197 } else {
175- RichString_setChar (& bar , startPos + j , '|' );
198+ RichString_setChar (& bar , charPos , '|' );
176199 }
177200 }
178- offset = nextOffset ;
179- }
180201
181- // ...then print the buffer.
182- offset = 0 ;
183- for (uint8_t i = 0 ; i < this -> curItems ; i ++ ) {
202+ offset += nCols ;
203+ charPos ++ ;
204+ }
205+
184206 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 ];
207+ RichString_setAttrn (& bar , CRT_colors [attr ], startPos , charPos - startPos );
188208 }
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 );
209+
210+ len = RichString_sizeVal (bar );
211+ if (charPos < len ) {
212+ RichString_setAttrn (& bar , CRT_colors [BAR_SHADOW ], charPos , len - charPos );
192213 }
214+ RichString_printVal (bar , y , x );
193215
194216 RichString_delete (& bar );
195217
0 commit comments