//  
//  Copyright (c) 1994 by Mike Romberg (  romberg@md.fsl.noaa.gov )
//  Debugged and Featurized by Michael Hemy
//
//  This file may be distributed under terms of the GPL
//

#include "xwin.h"
#include <iostream.h>
#include <unistd.h>
#include <stdio.h>


XWin::XWin( int argc, char *argv[], int width, int height, const char *title,
	   const char *foreground, const char *background, const char *font,
	   const char *color1, const char *color2, const char*color3,
	   const char *colorn) {
  hint_.x = hint_.y = 0;
  hint_.min_width = width;
  hint_.min_height = height;
  positionit_ = 0;
  if ( argc != 1 ){
    int i = 1;
    while( i < argc - 1 ){
      if ( !strcmp( argv[i], "-bg" )) {
	i++;
	if (i != argc) 
	  background = argv[i];
      }
      if ( !strcmp( argv[i], "-fg" )) {
	i++;
	if (i != argc) 
	  foreground = argv[i];
      }
      if ( !strcmp( argv[i], "-c1" )) {
	i++;
	if (i != argc) 
	  color1 = argv[i];
      }
      if ( !strcmp( argv[i], "-c2" )) {
	i++;
	if (i != argc) 
	  color2 = argv[i];
      }
      if ( !strcmp( argv[i], "-c3" )) {
	i++;
	if (i != argc) 
	  color3 = argv[i];
      }
      if ( !strcmp( argv[i], "-cn" )) {
	i++;
	if (i != argc) 
	  colorn = argv[i];
      }
      if ( !strcmp( argv[i], "-fn" )) {
	i++;
	if (i != argc) 
	  font = argv[i];
      }
      if ( !strcmp( argv[i], "-geometry" ) ){
	i++;
	if ( i != argc )
	  if ( sscanf( argv[i], "%dx%d%d%d", 
		      &width, &height, &hint_.x, &hint_.y ) == 4 )
	    positionit_ = 1;
      }
      i++;
    }
  }
  init( width, height, title, foreground, background, font,
       color1, color2, color3, colorn);
}

void XWin::init(int width, int height, const char *title, 
		const char *foreground, 
		const char *background, const char *font,
		const char *color1, const char *color2,
		const char *color3, const char *colorn) {
  height_ = height;
  width_  = width;
  iconname_ = title_ = NULL;
  if ( (disp_ = XOpenDisplay(0)) == NULL ){
    cerr <<"XWin::XWin() : error opening display" <<endl;
    exit( 1 );
  }
  screen_ = DefaultScreen( disp_ );

  fg_pixel_ = getforegroundcolor( foreground );
  bg_pixel_ = getbackgroundcolor( background );
  busy_pixel_[0] = getforegroundcolor( color1 );
  busy_pixel_[1] = getforegroundcolor( color2 );
  busy_pixel_[2] = getforegroundcolor( color3 );
  busy_pixel_[3] = getbackgroundcolor( colorn );
  free_pixel_ =    getbackgroundcolor( colorn );
  if ( hint_.x < 0 )
    hint_.x += ( -width_ + WidthOfScreen( DefaultScreenOfDisplay( disp_ ) ) );
  if ( hint_.y < 0 )
    hint_.y += ( -height + HeightOfScreen( DefaultScreenOfDisplay( disp_ ) ) );

  hint_.width = width_; hint_.height = height_;
  hint_.flags = USSize | PMinSize;
  if ( positionit_ ) {
    hint_.flags = hint_.flags | USPosition;
  }
  depth_ = DefaultDepth(disp_, screen_);
  window_ = XCreateSimpleWindow(disp_, DefaultRootWindow(disp_),
				hint_.x, hint_.y, hint_.width, hint_.height, 
				5, fg_pixel_, bg_pixel_ );
  gc_ = XCreateGC (disp_, window_, 0, 0);
  XSetWMProperties(disp_, window_, 0, 0, 0, 0, &hint_, 0, 0);

  XSetGraphicsExposures(disp_, gc_, 0);
  xfont_ = XLoadQueryFont(disp_, font);
  if (!xfont_) {
    fprintf(stderr, " font %s was not found, using fixed font\n", font);
    xfont_ = XLoadQueryFont(disp_, "fixed");
  }
  font_ = xfont_->fid;
  XSetFont(disp_, gc_, font_);
  font_height_ = (int)(xfont_->max_bounds.ascent + xfont_->max_bounds.descent);
  font_width_ = (int)(xfont_->max_bounds.rbearing - xfont_->min_bounds.lbearing);
  xoff_left_ = 4 * font_width_ + 10;
  yoff_above_ = 6 + xfont_->max_bounds.ascent;
  yoff_below_ = 4 + xfont_->max_bounds.descent;
  XSelectInput (disp_, window_,
		KeyPressMask | KeyReleaseMask | StructureNotifyMask 
		| ButtonPressMask | ButtonReleaseMask | VisibilityChangeMask);
  XSetForeground( disp_, gc_, fg_pixel_ );
  XSetBackground( disp_, gc_, bg_pixel_ );
  map();
  XWin::title( title );
  XWin::iconname( title );
  flush();


  int done = 0;
  XEvent event;
  while ( !done ){
    while (XEventsQueued(disp_,QueuedAfterReading)){
      XNextEvent(disp_,&event);
      if ( event.type == MapNotify ) done = 1;
    }
    sleep( 1 );
  }
}

XWin::~XWin() {
  XFreeGC (disp_, gc_);
  XDestroyWindow (disp_, window_);
  XCloseDisplay (disp_);
}

void XWin::title( const char *title ){
  delete[] title_;
  title_ = new char[ strlen( title ) + 1 ];
  strcpy( title_, title );
  XStoreName( disp_, window_, title_ );
}

void XWin::iconname( const char *name ){
  delete[] iconname_;
  iconname_ = new char[ strlen( name ) + 1 ];
  strcpy( iconname_, name );  
  XSetIconName( disp_, window_, iconname_ );
}

void XWin::buttonpress(){
}

void XWin::buttonrelease(){
}

void XWin::resize() {
  XClearWindow( disp_, window_ );
  XFlush(disp_);
  draw();
}

void XWin::checkevent() 
{
  int len;
  char ch[20];
  XEvent event;
  KeySym key;

  while (XEventsQueued(disp_,QueuedAfterReading)) {
    XNextEvent(disp_,&event);
    switch (event.type) {
    case KeyRelease:
      len=XLookupString (&event.xkey, ch, 10, &key, 0);
      if (len>0)
	keyrelease(ch);
      break;
    case ButtonRelease:
      buttonrelease();
      break;
    case ButtonPress:
      buttonpress();
      break;
    case ConfigureNotify:
//      cerr <<"XWin::checkevent : event.type ConfigureNotify: "
//	   <<event.type <<endl;
      if ( (width_ != event.xconfigure.width) || 
	   (height_ != event.xconfigure.height ) ){
	width_ = event.xconfigure.width;
	height_ = event.xconfigure.height;
	resize();
      }
      break;
    case VisibilityNotify:
//      cerr <<"XWin::checkevent : event.type VisibilityNotify: "
//	   <<event.type <<endl;
      visnotify();
      break;
    case MapNotify:
//      cerr <<"XWin::checkevent : event.type MapNotify: "
//	     <<event.type <<endl;
      mapnotify();
      break;
    case MappingNotify:
//      cerr <<"XWin::checkevent : event.type MappingNotify: "
//	     <<event.type <<endl;
      resize();
      break;
    case Expose:
//      cerr <<"XWin::checkevent : event.type Expose: " <<event.type <<endl;
//      cerr <<"XWin::checkevent : event.xexpose.count: "
//	     <<event.xexpose.count <<endl;
      resize();
      break;
    case GraphicsExpose:
//      cerr <<"XWin::checkevent : event.type GraphicsExpose: " <<event.type
//	     <<endl;
//      cerr <<"XWin::checkevent : event.xgraphicsexpose.count: "
//	     <<event.xgraphicsexpose.count <<endl;
      resize();
      break;
    }
  }
}

void XWin::keyrelease(char *ch) {
  cerr <<ch[0] <<endl;
  if ((*ch == 'q') || (*ch =='Q'))
    exit(0);
}

void XWin::clearwin() {
  XClearWindow( disp_, window_ );
  XFlush(disp_);
}

int XWin::getforegroundcolor( const char *name ){
  XColor tmp;
  
  if ((!name) ||
      (!XAllocNamedColor( disp_, DefaultColormap(disp_, screen_ ), name,
			 &tmp, &tmp ))) 
    return(WhitePixel( disp_, screen_ ));
  return(tmp.pixel );
}

int XWin::getbackgroundcolor( const char *name ){
  XColor tmp;

  if ((!name) ||
      (!XAllocNamedColor( disp_, DefaultColormap( disp_, screen_ ), name,
			 &tmp, &tmp ))) 
    return(BlackPixel( disp_, screen_ ));
  return( tmp.pixel );
}
