"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 }