xosview  1.23
About: xosview is an X Windows based system monitor (cpu, memory, swap and network usage; interrupt and serial activities; load average).
  Fossies Dox: xosview-1.23.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

bitfieldmeter.cc
Go to the documentation of this file.
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;
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
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 
56  delete[] bits_;
57  delete[] lastbits_;
58  delete[] fields_;
59  delete[] colors_;
60  delete[] lastvals_;
61  delete[] lastx_;
62 }
63 
66  usedcolor_ = parent_->allocColor( parent_->getResource( "usedLabelColor") );
67 }
68 
69 
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_) {
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. */
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_ ){
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_){
161  parent_->drawString( x_, y_ - 5, legend_ );
162  drawfieldlegend();
163  }
164  }
165  drawBits( 1 );
166  drawfields( 1 );
167 }
168 
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);
187  parent_->drawString( x, y_ - 5, buff );
188  x += parent_->textWidth( buff, n );
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 
241  usedoffset_ - onechar / 2, parent_->textHeight() + 1 );
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 )
261  else
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]) ){
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 
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 
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 }
char * fieldLegend_
Definition: bitfieldmeter.h:69
unsigned long usedcolor_
Definition: bitfieldmeter.h:51
void drawused(int mandatory)
void checkevent(void)
BitFieldMeter(XOSView *parent, int numBits=1, int numfields=1, const char *title="", const char *bitlegend="", const char *fieldlegend="", int docaptions=0, int dolegends=0, int dousedlegends=0)
UsedType print_
Definition: bitfieldmeter.h:52
void reset(void)
void drawBits(int mandatory=0)
unsigned long * colors_
Definition: bitfieldmeter.h:50
void setUsed(double val, double total)
virtual ~BitFieldMeter(void)
void setBits(int startbit, unsigned char values)
virtual void drawfields(int mandatory=0)
void setNumFields(int n)
double * fields_
Definition: bitfieldmeter.h:47
void setNumBits(int n)
double lastused_
Definition: bitfieldmeter.h:48
void setfieldlegend(const char *fieldlegend)
void SetUsedFormat(const char *const str)
unsigned long onColor_
Definition: bitfieldmeter.h:58
char * lastbits_
Definition: bitfieldmeter.h:59
void draw(void)
bool checkX(int x, int width) const
virtual void checkResources(void)
unsigned long offColor_
Definition: bitfieldmeter.h:58
void drawfieldlegend(void)
int printedZeroTotalMesg_
Definition: bitfieldmeter.h:53
void disableMeter(void)
void setfieldcolor(int field, const char *color)
Definition: meter.h:14
int x_
Definition: meter.h:53
int docaptions_
Definition: meter.h:53
int dolegends_
Definition: meter.h:53
virtual void checkResources(void)
Definition: meter.cc:33
int y_
Definition: meter.h:53
int dousedlegends_
Definition: meter.h:53
int width_
Definition: meter.h:53
char * legend_
Definition: meter.h:55
virtual const char * name(void) const
Definition: meter.h:20
static double scaleValue(double value, char *scale, bool metric)
Definition: meter.cc:67
unsigned long textcolor_
Definition: meter.h:56
char * title_
Definition: meter.h:55
XOSView * parent_
Definition: meter.h:52
int height_
Definition: meter.h:53
unsigned long foreground(void)
Definition: xwin.h:53
unsigned long allocColor(const char *name)
Definition: xwin.cc:383
void setForeground(unsigned long pixelvalue)
Definition: xwin.h:38
void drawString(int x, int y, const char *str)
Definition: xwin.h:69
int textHeight(void)
Definition: xwin.h:79
void setStippleN(int n)
Definition: xwin.h:48
void lineWidth(int width)
Definition: xwin.h:57
void drawRectangle(int x, int y, int width, int height)
Definition: xwin.h:65
int textWidth(const char *str, int n)
Definition: xwin.h:73
const char * getResource(const char *name)
Definition: xwin.cc:362
void clear(void)
Definition: xwin.h:34
void drawFilledRectangle(int x, int y, int width, int height)
Definition: xwin.h:67