@@ -81,14 +81,17 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
8181 assert (x >= 0 );
8282 assert (w <= INT_MAX - x );
8383
84+ const char * ptr ;
85+ int nCols ;
86+
8487 // Draw the caption
8588 const int captionWidth = 3 ;
8689 const char * caption = Meter_getCaption (this );
8790 if (w >= captionWidth ) {
8891 attrset (CRT_colors [METER_TEXT ]);
8992
90- const char * ptr = caption ;
91- int nCols = String_mbswidth (& ptr , 256 , captionWidth );
93+ ptr = caption ;
94+ nCols = String_mbswidth (& ptr , 256 , captionWidth );
9295 int len = (int )(ptr - caption );
9396 mvprintw (y , x , "%-*.*s" , len + captionWidth - nCols , len , caption );
9497 }
@@ -110,71 +113,93 @@ static void BarMeterMode_draw(Meter* this, int x, int y, int w) {
110113 attrset (CRT_colors [RESET_COLOR ]); // Clear the bold attribute
111114 x ++ ;
112115
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.
131117
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
135119
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 , ' ' );
139122
140- int blockSizes [10 ];
123+ RichString_begin (bar );
124+ RichString_appendChr (& bar , 0 , ' ' , w - nCols );
125+ RichString_appendnWide (& bar , 0 , this -> txtBuffer , (int )(ptr - this -> txtbuffer ));
141126
142- // First draw in the bar[] buffer...
127+ size_t charPos = 0 ;
143128 int offset = 0 ;
144129 for (uint8_t i = 0 ; i < this -> curItems ; i ++ ) {
130+ if (!(this -> total > 0.0 )) {
131+ break ;
132+ }
133+ if (offset >= w ) {
134+ break ;
135+ }
136+
145137 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 ;
138+ if (!isPositive (value )) {
139+ continue ;
152140 }
153- int nextOffset = offset + blockSizes [i ];
154- for (int j = offset ; j < nextOffset ; j ++ )
155- if (RichString_getCharVal (bar , startPos + j ) == ' ' ) {
141+ value = MINIMUM (value , this -> total );
142+ int blockSize = ceil ((value / this -> total ) * w );
143+ blockSize = MINIMUM (blockSize , w - offset );
144+ if (blockSize < 1 ) {
145+ continue ;
146+ }
147+
148+ int nextOffset = offset + blockSize ;
149+ assert (offset < nextOffset );
150+
151+ size_t startPos = charPos ;
152+ while (true) {
153+ if (offset >= nextOffset ) {
154+ #ifdef HAVE_LIBNCURSESW
155+ if (!CRT_utf8 ) {
156+ break ;
157+ }
158+ #else
159+ break ;
160+ #endif
161+ }
162+
163+ #ifdef HAVE_LIBNCURSESW
164+ wchar_t ch = RichString_getCharVal (bar , charPos );
165+ if (ch == 0 )
166+ break ;
167+
168+ nCols = wcwidth (ch );
169+ assert (nCols >= 0 );
170+
171+ if (offset >= nextOffset && nCols > 0 ) {
172+ // This break condition is for UTF-8.
173+ break ;
174+ }
175+ #else
176+ char ch = RichString_getCharVal (bar , charPos );
177+ nCols = 1 ;
178+
179+ assert (offset < nextOffset );
180+ #endif
181+ if (ch == ' ' ) {
156182 if (CRT_colorScheme == COLORSCHEME_MONOCHROME ) {
157183 assert (i < strlen (BarMeterMode_characters ));
158- RichString_setChar (& bar , startPos + j , BarMeterMode_characters [i ]);
184+ RichString_setChar (& bar , charPos , BarMeterMode_characters [i ]);
159185 } else {
160- RichString_setChar (& bar , startPos + j , '|' );
186+ RichString_setChar (& bar , charPos , '|' );
161187 }
162188 }
163- offset = nextOffset ;
164- }
165189
166- // ...then print the buffer.
167- offset = 0 ;
168- for (uint8_t i = 0 ; i < this -> curItems ; i ++ ) {
190+ offset += nCols ;
191+ charPos ++ ;
192+ }
193+
169194 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 ];
195+ RichString_setAttrn (& bar , CRT_colors [attr ], startPos , charPos - startPos );
173196 }
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 );
197+
198+ len = RichString_sizeVal (bar );
199+ if (charPos < len ) {
200+ RichString_setAttrn (& bar , CRT_colors [BAR_SHADOW ], charPos , len - charPos );
177201 }
202+ RichString_printVal (bar , y , x );
178203
179204 RichString_delete (& bar );
180205
0 commit comments