//
// Copyright (c) 1994, 1995, 2002, 2006 by Mike Romberg ( mike.romberg@noaa.gov )
//
// This file may be distributed under terms of the GPL
//
//
// $Id$
//
#include <unistd.h>
#include <stdlib.h>
#include <sys/time.h>
#include "snprintf.h"
#include "general.h"
#include "xosview.h"
#include "meter.h"
#include "MeterMaker.h"
#if (defined(XOSVIEW_NETBSD) || defined(XOSVIEW_FREEBSD) || defined(XOSVIEW_OPENBSD))
#include "kernel.h"
#endif
static const char * const versionString = "xosview version: " XOSVIEW_VERSION;
static const char NAME[] = "xosview@";
#if !defined(__GNUC__)
#define MIN(x,y) \
( \
x < y ? x : y \
)
#define MAX(x,y) \
( \
x > y ? x : y \
)
#else
#define MIN(x,y) \
({ \
const typeof(x) _x = x; \
const typeof(y) _y = y; \
\
(void) (&_x == &_y); \
\
_x < _y ? _x : _y; \
})
#define MAX(x,y) \
({ \
const typeof(x) _x = x; \
const typeof(y) _y = y; \
\
(void) (&_x == &_y); \
\
_x > _y ? _x : _y; \
})
#endif // sgi
double MAX_SAMPLES_PER_SECOND = 10;
CVSID("$Id$");
CVSID_DOT_H(XOSVIEW_H_CVSID);
XOSView::XOSView( char * instName, int argc, char *argv[] ) : XWin(),
xrm(Xrm("xosview", instName)){
// Check for version arguments first. This allows
// them to work without the need for a connection
// to the X server
checkVersion(argc, argv);
setDisplayName (xrm.getDisplayName( argc, argv));
openDisplay(); // So that the Xrm class can contact the display for its
// default values.
// The resources need to be initialized before calling XWinInit, because
// XWinInit looks at the geometry resource for its geometry. BCG
xrm.loadAndMergeResources (argc, argv, display_);
XWinInit (argc, argv, NULL, &xrm);
#if 1 // Don't enable this yet.
MAX_SAMPLES_PER_SECOND = atof(getResource("samplesPerSec"));
if (!MAX_SAMPLES_PER_SECOND)
MAX_SAMPLES_PER_SECOND = 10;
#endif
usleeptime_ = (unsigned long) (1000000/MAX_SAMPLES_PER_SECOND);
if (usleeptime_ >= 1000000) {
/* The syscall usleep() only takes times less than 1 sec, so
* split into a sleep time and a usleep time if needed. */
sleeptime_ = usleeptime_ / 1000000;
usleeptime_ = usleeptime_ % 1000000;
} else { sleeptime_ = 0; }
#if (defined(XOSVIEW_NETBSD) || defined(XOSVIEW_FREEBSD) || defined(XOSVIEW_OPENBSD))
BSDInit(); /* Needs to be done before processing of -N option. */
#endif
hmargin_ = atoi(getResource("horizontalMargin"));
vmargin_ = atoi(getResource("verticalMargin"));
vspacing_ = atoi(getResource("verticalSpacing"));
hmargin_ = MAX(0, hmargin_);
vmargin_ = MAX(0, vmargin_);
vspacing_ = MAX(0, vspacing_);
checkArgs (argc, argv); // Check for any other unhandled args.
xoff_ = hmargin_;
yoff_ = 0;
nummeters_ = 0;
meters_ = NULL;
name_ = "xosview";
_isvisible = false;
_ispartiallyvisible = false;
exposed_once_flag_ = 0;
expose_flag_ = 1;
// set up the X events
addEvent( new Event( this, ConfigureNotify,
(EventCallBack)&XOSView::resizeEvent ) );
addEvent( new Event( this, Expose,
(EventCallBack)&XOSView::exposeEvent ) );
addEvent( new Event( this, KeyPress,
(EventCallBack)&XOSView::keyPressEvent ) );
addEvent( new Event( this, VisibilityNotify,
(EventCallBack)&XOSView::visibilityEvent ) );
addEvent( new Event( this, UnmapNotify,
(EventCallBack)&XOSView::unmapEvent ) );
// add or change the Resources
MeterMaker mm(this);
// see if legends are to be used
checkOverallResources ();
// add in the meters
mm.makeMeters();
for (int i = 1 ; i <= mm.n() ; i++)
addmeter(mm[i]);
if (nummeters_ == 0)
{
fprintf (stderr, "No meters were enabled! Exiting...\n");
exit (0);
}
// Have the meters re-check the resources.
checkMeterResources();
// determine the width and height of the window then create it
figureSize();
init( argc, argv );
title( winname() );
iconname( winname() );
dolegends();
resize();
}
void XOSView::checkVersion(int argc, char *argv[]) const
{
for (int i = 0 ; i < argc ; i++)
if (!strncasecmp(argv[i], "-v", 2)
|| !strncasecmp(argv[i], "--version", 10))
{
std::cerr << versionString << std::endl;
exit(0);
}
}
void XOSView::figureSize ( void ) {
if ( legend_ ){
if ( !usedlabels_ )
xoff_ = textWidth( "XXXXX" );
else
xoff_ = textWidth( "XXXXXXXXX" );
yoff_ = caption_ ? textHeight() + textHeight() / 4 : 0;
}
static int firsttime = 1;
if (firsttime) {
firsttime = 0;
width_ = findx();
height_ = findy();
}
else
{
}
}
void XOSView::checkMeterResources( void ){
MeterNode *tmp = meters_;
while ( tmp != NULL ){
tmp->meter_->checkResources();
tmp = tmp->next_;
}
}
int XOSView::newypos( void ){
return 15 + 25 * nummeters_;
}
void XOSView::dolegends( void ){
MeterNode *tmp = meters_;
while ( tmp != NULL ){
tmp->meter_->docaptions( caption_ );
tmp->meter_->dolegends( legend_ );
tmp->meter_->dousedlegends( usedlabels_ );
tmp = tmp->next_;
}
}
void XOSView::addmeter( Meter *fm ){
MeterNode *tmp = meters_;
if ( meters_ == NULL )
meters_ = new MeterNode( fm );
else {
while ( tmp->next_ != NULL )
tmp = tmp->next_;
tmp->next_ = new MeterNode( fm );
}
nummeters_++;
}
int XOSView::findx( void ){
if ( legend_ ){
if ( !usedlabels_ )
return textWidth( "XXXXXXXXXXXXXXXXXXXXXXXX" );
else
return textWidth( "XXXXXXXXXXXXXXXXXXXXXXXXXXXXX" );
}
return 80;
}
int XOSView::findy( void ){
if ( legend_ )
return 10 + textHeight() * nummeters_ * ( caption_ ? 2 : 1 );
return 15 * nummeters_;
}
void XOSView::checkOverallResources() {
// Check various resource values.
// Set 'off' value. This is not necessarily a default value --
// the value in the defaultXResourceString is the default value.
usedlabels_ = legend_ = caption_ = 0;
setFont();
// use captions
if ( isResourceTrue("captions") )
caption_ = 1;
// use labels
if ( isResourceTrue("labels") )
legend_ = 1;
// use "free" labels
if ( isResourceTrue("usedlabels") )
usedlabels_ = 1;
}
const char *XOSView::winname( void ){
char host[100];
gethostname( host, 99 );
static char name[101]; /* We return a pointer to this,
so it can't be local. */
snprintf( name, 100, "%s%s", NAME, host);
// Allow overriding of this name through the -title option.
return getResourceOrUseDefault ("title", name);
}
void XOSView::resize( void ){
int spacing = vspacing_+1;
int topmargin = vmargin_;
int rightmargin = hmargin_;
int newwidth = width_ - xoff_ - rightmargin;
/*
int newheight = (height_ - (10 + 5 * (nummeters_ - 1) +
nummeters_ * yoff_)) / nummeters_;
*/
int newheight =
(height_ -
(topmargin + topmargin + (nummeters_-1)*spacing + nummeters_*yoff_)
) / nummeters_;
newheight = (newheight >= 2) ? newheight : 2;
int counter = 1;
MeterNode *tmp = meters_;
while ( tmp != NULL ) {
/*
tmp->meter_->resize( xoff_, 5 * counter + counter * yoff_ +
(counter - 1) * newheight, newwidth, newheight );
*/
tmp->meter_->resize( xoff_,
topmargin + counter*yoff_ + (counter-1)*(newheight+spacing),
newwidth, newheight );
tmp = tmp->next_;
counter++;
}
}
XOSView::~XOSView( void ){
MeterNode *tmp = meters_;
while ( tmp != NULL ){
MeterNode *save = tmp->next_;
delete tmp->meter_;
delete tmp;
tmp = save;
}
}
void XOSView::reallydraw( void ){
XOSDEBUG("Doing draw.\n");
clear();
MeterNode *tmp = meters_;
while ( tmp != NULL ){
tmp->meter_->draw();
tmp = tmp->next_;
}
flush();
expose_flag_ = 0;
}
void XOSView::draw ( void ) {
if (hasBeenExposedAtLeastOnce() && isAtLeastPartiallyVisible())
reallydraw();
else {
if (!hasBeenExposedAtLeastOnce()) {
XOSDEBUG("Skipping draw: not yet exposed.\n");
} else if (!isAtLeastPartiallyVisible()) {
XOSDEBUG("Skipping draw: not visible.\n");
}
}
}
void XOSView::keyrelease( char *ch ){
/* WARNING: This code is not called by anything. */
(void) ch; /* To avoid gcc warnings. */
}
void XOSView::run( void ){
int counter = 0;
while( !done_ ){
checkevent();
if (_isvisible){
MeterNode *tmp = meters_;
while ( tmp != NULL ){
if ( tmp->meter_->requestevent() )
tmp->meter_->checkevent();
tmp = tmp->next_;
}
flush();
}
#ifdef HAVE_USLEEP
/* First, sleep for the proper integral number of seconds --
* usleep only deals with times less than 1 sec. */
if (sleeptime_) sleep((unsigned int)sleeptime_);
if (usleeptime_) usleep( (unsigned int)usleeptime_);
#else
usleep_via_select ( usleeptime_ );
#endif
counter = (counter + 1) % 5;
}
}
void XOSView::usleep_via_select( unsigned long usec ){
struct timeval time;
time.tv_sec = (int)(usec / 1000000);
time.tv_usec = usec - time.tv_sec * 1000000;
select( 0, 0, 0, 0, &time );
}
void XOSView::keyPressEvent( XKeyEvent &event ){
char c = 0;
KeySym key;
XLookupString( &event, &c, 1, &key, NULL );
if ( (c == 'q') || (c == 'Q') )
done_ = 1;
}
void XOSView::checkArgs (int argc, char** argv) const
{
// The XWin constructor call in the XOSView constructor above
// modifies argc and argv, so by this
// point, all XResource arguments should be removed. Since we currently
// don't have any other command-line arguments, perform a check here
// to make sure we don't get any more.
if (argc == 1) return; // No arguments besides X resources.
// Skip to the first real argument.
argc--;
argv++;
while (argc > 0 && argv && *argv)
{
switch (argv[0][1]) {
case 'n': // Check for -name option that was already parsed
// and acted upon by main().
if (!strncasecmp(*argv, "-name", 6))
{
argv++; // Skip arg to -name.
argc--;
}
break;
#if (defined(XOSVIEW_NETBSD) || defined(XOSVIEW_FREEBSD) || defined(XOSVIEW_OPENBSD))
case 'N': if (strlen(argv[0]) > 2)
SetKernelName(argv[0]+2);
else
{
SetKernelName(argv[1]);
argc--;
argv++;
}
break;
#endif
/* Fall through to default/error case. */
default:
std::cerr << "Ignoring unknown option '" << argv[0] << "'.\n";
break;
}
argc--;
argv++;
}
}
void XOSView::exposeEvent( XExposeEvent &event ) {
_isvisible = true;
if ( event.count == 0 )
{
expose_flag_++;
draw();
}
XOSDEBUG("Got expose event.\n");
if (!exposed_once_flag_) { exposed_once_flag_ = 1; draw(); }
}
void XOSView::resizeEvent( XEvent & ) {
resize();
expose_flag_++;
draw();
}
void XOSView::visibilityEvent( XVisibilityEvent &event ){
_ispartiallyvisible = false;
if (event.state == VisibilityPartiallyObscured){
_ispartiallyvisible = true;
}
if (event.state == VisibilityFullyObscured){
_isvisible = false;
}
else {
_isvisible = true;
}
XOSDEBUG("Got visibility event; %d and %d\n",
_ispartiallyvisible, _isvisible);
}
void XOSView::unmapEvent( XUnmapEvent & ){
_isvisible = false;
}
syntax highlighted by Code2HTML, v. 0.9.1