"Fossies" - the Fresh Open Source Software Archive 
Member "xosview-1.23/bitfieldmeter.cc" (11 Jul 2020, 10481 Bytes) of package /linux/misc/xosview-1.23.tar.gz:
As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style:
standard) with prefixed line numbers and
code folding option.
Alternatively you can here
view or
download the uninterpreted source code file.
For more information about "bitfieldmeter.cc" see the
Fossies "Dox" file reference documentation.
1 //
2 // Copyright (c) 1999, 2006 Thomas Waldmann ( ThomasWaldmann@gmx.de )
3 // based on work of Mike Romberg ( mike.romberg@noaa.gov )
4 //
5 // This file may be distributed under terms of the GPL
6 //
7 //
8
9 #include "bitfieldmeter.h"
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <math.h>
14 #include <iostream>
15
16
17 BitFieldMeter::BitFieldMeter( XOSView *parent, int numBits, int numfields,
18 const char *title,
19 const char *bitslegend, const char *FieldLegend,
20 int docaptions, int dolegends, int dousedlegends )
21 : Meter(parent, title, bitslegend, docaptions, dolegends, dousedlegends){
22 /* We need to set print_ to something valid -- the meters
23 * apparently get drawn before the meters have a chance to call
24 * CheckResources() themselves. */
25 bits_ = NULL;
26 lastbits_ = NULL;
27 numWarnings_ = printedZeroTotalMesg_ = 0;
28 print_ = PERCENT;
29 metric_ = false;
30 usedoffset_ = 0;
31 used_ = 0;
32 lastused_ = -1;
33 fields_ = NULL;
34 colors_ = NULL;
35 lastvals_ = NULL;
36 lastx_ = NULL;
37 setNumBits(numBits);
38 fieldLegend_ = NULL;
39 setfieldlegend(FieldLegend);
40 setNumFields(numfields);
41 }
42
43 void
44 BitFieldMeter::disableMeter ( )
45 {
46 setNumFields(1);
47 setfieldcolor (0, "grey");
48 setfieldlegend ("Disabled");
49 total_ = fields_[0] = 1.0;
50 setNumBits(1);
51 offColor_ = onColor_ = parent_->allocColor("grey");
52 }
53
54
55 BitFieldMeter::~BitFieldMeter( void ){
56 delete[] bits_;
57 delete[] lastbits_;
58 delete[] fields_;
59 delete[] colors_;
60 delete[] lastvals_;
61 delete[] lastx_;
62 }
63
64 void BitFieldMeter::checkResources( void ){
65 Meter::checkResources();
66 usedcolor_ = parent_->allocColor( parent_->getResource( "usedLabelColor") );
67 }
68
69
70 void BitFieldMeter::setNumBits(int n){
71 numbits_ = n;
72 delete[] bits_;
73 delete[] lastbits_;
74
75 bits_ = new char[numbits_];
76 lastbits_ = new char[numbits_];
77
78 for ( int i = 0 ; i < numbits_ ; i++ )
79 bits_[i] = lastbits_[i] = 0;
80 }
81
82 void BitFieldMeter::SetUsedFormat ( const char * const fmt ) {
83 /* Do case-insensitive compares. */
84 if (!strncasecmp (fmt, "percent", 8))
85 print_ = PERCENT;
86 else if (!strncasecmp (fmt, "autoscale", 10))
87 print_ = AUTOSCALE;
88 else if (!strncasecmp (fmt, "float", 6))
89 print_ = FLOAT;
90 else {
91 std::cerr << "Error: could not parse format of '" << fmt << "'.\n"
92 << " I expected one of 'percent', 'autoscale', or 'float'"
93 << " (Case-insensitive)." << std::endl;
94 exit(1);
95 }
96 }
97
98 void BitFieldMeter::setUsed (double val, double total)
99 {
100 if (print_ == FLOAT)
101 used_ = val;
102 else if (print_ == PERCENT)
103 {
104 if (total != 0.0)
105 used_ = val / total * 100.0;
106 else
107 {
108 if (!printedZeroTotalMesg_) {
109 printedZeroTotalMesg_ = 1;
110 std::cerr << "Warning: " << name() << " meter had a zero total field! "
111 << "Would have caused a div-by-zero exception." << std::endl;
112 }
113 used_ = 0.0;
114 }
115 }
116 else if (print_ == AUTOSCALE)
117 used_ = val;
118 else {
119 std::cerr << "Error in " << name() << ": I can't handle a UsedType enum "
120 << "value of " << print_ << "!" << std::endl;
121 exit(1);
122 }
123 }
124
125 void BitFieldMeter::reset( void ){
126 for ( int i = 0 ; i < numfields_ ; i++ )
127 lastvals_[i] = lastx_[i] = -1;
128 }
129
130 void BitFieldMeter::setfieldcolor( int field, const char *color ){
131 colors_[field] = parent_->allocColor( color );
132 }
133
134 void BitFieldMeter::setfieldcolor( int field, unsigned long color ) {
135 colors_[field] = color;
136 }
137
138
139 void BitFieldMeter::draw( void ){
140 /* Draw the outline for the fieldmeter. */
141 parent_->setForeground( parent_->foreground() );
142 parent_->lineWidth( 1 );
143 parent_->drawFilledRectangle( x_ - 1, y_ - 1, width_/2 + 2, height_ + 2 );
144
145 // ?? parent_->lineWidth( 0 );
146
147 parent_->drawRectangle( x_ + width_/2 +3, y_ - 1, width_/2 - 2, height_ + 2 );
148 if ( dolegends_ ){
149 parent_->setForeground( textcolor_ );
150
151 int offset;
152 if ( dousedlegends_ )
153 offset = parent_->textWidth( "XXXXXXXXXX" );
154 else
155 offset = parent_->textWidth( "XXXXXX" );
156
157 parent_->drawString( x_ - offset + 1, y_ + height_, title_ );
158
159 if(docaptions_){
160 parent_->setForeground( onColor_ );
161 parent_->drawString( x_, y_ - 5, legend_ );
162 drawfieldlegend();
163 }
164 }
165 drawBits( 1 );
166 drawfields( 1 );
167 }
168
169 void BitFieldMeter::drawfieldlegend( void ){
170 char *tmp1, *tmp2, buff[100];
171 int n, x = x_ + width_/2 + 4;
172
173 tmp1 = tmp2 = fieldLegend_;
174 for ( int i = 0 ; i < numfields_ ; i++ ){
175 n = 0;
176 while ( (*tmp2 != '/') && (*tmp2 != '\0') ){
177 if ( (*tmp2 == '\\') && (*(tmp2 + 1) == '/') ) // allow '/' in field as '\/'
178 memmove( tmp2, tmp2 + 1, strlen(tmp2) );
179 tmp2++;
180 n++;
181 }
182 tmp2++;
183 strncpy( buff, tmp1, n );
184 buff[n] = '\0';
185 parent_->setStippleN(i%4);
186 parent_->setForeground( colors_[i] );
187 parent_->drawString( x, y_ - 5, buff );
188 x += parent_->textWidth( buff, n );
189 parent_->setForeground( parent_->foreground() );
190 if ( i != numfields_ - 1 )
191 parent_->drawString( x, y_ - 5, "/" );
192 x += parent_->textWidth( "/", 1 );
193 tmp1 = tmp2;
194 }
195 parent_->setStippleN(0); /* Restore default all-bits stipple. */
196 }
197
198 void BitFieldMeter::drawused( int mandatory ){
199 if ( !mandatory )
200 if ( lastused_ == used_ )
201 return;
202
203 parent_->setStippleN(0); /* Use all-bits stipple. */
204 static const int onechar = parent_->textWidth( "X" );
205 if (!usedoffset_) // metric meters need extra space for '-' sign
206 usedoffset_ = ( metric_ ? parent_->textWidth( "XXXXXX" )
207 : parent_->textWidth( "XXXXX" ) );
208 char buf[10];
209
210 if (print_ == PERCENT){
211 snprintf( buf, 10, "%d%%", (int)used_ );
212 }
213 else if (print_ == AUTOSCALE){
214 char scale[2];
215 double scaled_used = scaleValue(used_, scale, metric_);
216 /* For now, we can only print 3 characters, plus the optional sign and
217 * suffix, without overprinting the legends. Thus, we can
218 * print 965, or we can print 34, but we can't print 34.7 (the
219 * decimal point takes up one character). bgrayson */
220 if (scaled_used == 0.0)
221 snprintf (buf, 10, "0");
222 else {
223 if (scaled_used < 0 && !metric_)
224 snprintf (buf, 10, "-");
225 else if ( fabs(scaled_used) < 9.95 )
226 // 9.95 or above would get
227 // rounded to 10.0, which is too wide.
228 snprintf (buf, 10, "%.1f%s", scaled_used, scale);
229 else
230 snprintf (buf, 10, "%.0f%s", scaled_used, scale);
231 }
232 }
233 else {
234 if ( fabs(used_) < 99.95 )
235 snprintf( buf, 10, "%.1f", used_ );
236 else // drop the decimal if the string gets too long
237 snprintf( buf, 10, "%.0f", used_ );
238 }
239
240 parent_->clear( x_ - usedoffset_, y_ + height_ - parent_->textHeight(),
241 usedoffset_ - onechar / 2, parent_->textHeight() + 1 );
242 parent_->setForeground( usedcolor_ );
243 parent_->drawString( x_ - (strlen( buf ) + 1 ) * onechar + 2,
244 y_ + height_, buf );
245 lastused_ = used_;
246 }
247
248 void BitFieldMeter::drawBits( int mandatory ){
249 static int pass = 1;
250
251 // pass = (pass + 1) % 2;
252
253 int x1 = x_, w;
254
255 w = (width_/2 - (numbits_+1)) / numbits_;
256
257 for ( int i = 0 ; i < numbits_ ; i++ ){
258 if ( (bits_[i] != lastbits_[i]) || mandatory ){
259 if ( bits_[i] && pass )
260 parent_->setForeground( onColor_ );
261 else
262 parent_->setForeground( offColor_ );
263 parent_->drawFilledRectangle( x1, y_, w, height_);
264 }
265
266 lastbits_[i] = bits_[i];
267
268 x1 += (w + 2);
269 }
270 }
271
272 void BitFieldMeter::drawfields( int mandatory ){
273 int twidth, x = x_ + width_/2 + 4;
274
275 if ( total_ == 0 )
276 return;
277
278 for ( int i = 0 ; i < numfields_ ; i++ ){
279 /* Look for bogus values. */
280 if (fields_[i] < 0.0 && !metric_) {
281 /* Only print a warning 5 times per meter, followed by a
282 * message about no more warnings. */
283 numWarnings_ ++;
284 if (numWarnings_ < 5)
285 std::cerr << "Warning: meter " << name() << " had a negative value of "
286 << fields_[i] << " for field " << i << std::endl;
287 if (numWarnings_ == 5)
288 std::cerr << "Future warnings from the " << name() << " meter will not "
289 << "be displayed." << std::endl;
290 }
291
292 twidth = (int)fabs(((width_/2 - 3) * fields_[i]) / total_);
293 if ( (i == numfields_ - 1) && ((x + twidth) != (x_ + width_)) )
294 twidth = width_ + x_ - x;
295
296 if ( mandatory || (twidth != lastvals_[i]) || (x != lastx_[i]) ){
297 parent_->setForeground( colors_[i] );
298 parent_->setStippleN(i%4);
299 parent_->drawFilledRectangle( x, y_, twidth, height_ );
300 parent_->setStippleN(0); /* Restore all-bits stipple. */
301 lastvals_[i] = twidth;
302 lastx_[i] = x;
303
304 if ( dousedlegends_ )
305 drawused( mandatory );
306 }
307 x += twidth;
308 }
309 }
310
311 void BitFieldMeter::checkevent( void ){
312 drawBits();
313 drawfields();
314 }
315
316 void BitFieldMeter::setBits(int startbit, unsigned char values){
317 unsigned char mask = 1;
318 for (int i = startbit ; i < startbit + 8 ; i++){
319 bits_[i] = values & mask;
320 mask = mask << 1;
321 }
322 }
323
324 void BitFieldMeter::setNumFields(int n){
325 numfields_ = n;
326 delete[] fields_;
327 delete[] colors_;
328 delete[] lastvals_;
329 delete[] lastx_;
330 fields_ = new double[numfields_];
331 colors_ = new unsigned long[numfields_];
332 lastvals_ = new int[numfields_];
333 lastx_ = new int[numfields_];
334
335 total_ = 0;
336 for ( int i = 0 ; i < numfields_ ; i++ ){
337 fields_[i] = 0.0; /* egcs 2.91.66 bug !? don't do this and */
338 lastvals_[i] = lastx_[i] = 0; /* that in a single statement or it'll */
339 /* overwrite too much with 0 ... */
340 /* Thomas Waldmann ( tw@com-ma.de ) */
341 }
342 }
343
344 bool BitFieldMeter::checkX(int x, int width) const {
345 if ((x < x_) || (x + width < x_)
346 || (x > x_ + width_) || (x + width > x_ + width_)){
347 std::cerr << "BitFieldMeter::checkX() : bad horiz values for meter : "
348 << name() << std::endl;
349
350 std::cerr <<"value "<<x<<", width "<<width<<", total_ = "<<total_<<std::endl;
351
352 for (int i = 0 ; i < numfields_ ; i++)
353 std::cerr <<"fields_[" <<i <<"] = " <<fields_[i] <<",";
354 std::cerr <<std::endl;
355
356 return false;
357 }
358
359 return true;
360 }
361
362
363 void BitFieldMeter::setfieldlegend( const char *fieldlegend ){
364 delete[] fieldLegend_;
365 int len = strlen(fieldlegend);
366 fieldLegend_ = new char[len + 1];
367 strncpy( fieldLegend_, fieldlegend, len );
368 fieldLegend_[len] = '\0'; // strncpy() will not null terminate if s2 > len
369 }