/*******************************************************************************
+
+  LEDA 3.5
+
+  _window.c
+
+  This file is part of the LEDA research version (LEDA-R) that can be 
+  used free of charge in academic research and teaching. Any commercial
+  use of this software requires a license which is distributed by the
+  LEDA Software GmbH, Postfach 151101, 66041 Saarbruecken, FRG
+  (fax +49 681 31104).
+
+  Copyright (c) 1991-1997  by  Max-Planck-Institut fuer Informatik
+  Im Stadtwald, 66123 Saarbruecken, Germany     
+  All rights reserved.
+ 
*******************************************************************************/
#include <LEDA/window.h>
#include <math.h>
#include <stdio.h>
#include <stdarg.h>
#include <string.h>


//------------------------------------------------------------------------------
// LEDA WINDOW BASICS
//------------------------------------------------------------------------------

//
// moved to _wglobal.c
//
// color window::fgcol = -1;
// color window::bgcol = -1;
//


window::window() : BASE_WINDOW(LEDA::copyright_string)
{ set_error_handler(win_error_handler);
  INIT_BUTTONS;
  OPEN_WINDOW;
 }

window::window(float w, float h) : BASE_WINDOW(int(w),int(h),LEDA::copyright_string)
{ set_error_handler(win_error_handler); 
  INIT_BUTTONS; 
  if (w>0 && h>0) OPEN_WINDOW;
 }

window::window(float w, float h, const char* label) : BASE_WINDOW(int(w),int(h),label)
{ LEDA::write_log(string("Window: %s",label));
  set_error_handler(win_error_handler); 
  INIT_BUTTONS; 
  if (w>0 && h>0) OPEN_WINDOW;
 }

window::window(const char* label) : BASE_WINDOW(label)
{ LEDA::write_log(string("Window: %s",label));
  set_error_handler(win_error_handler);
  INIT_BUTTONS;
  OPEN_WINDOW;
 }


void window::win_error_handler(int i, const char* s)
{ 
  panel P("LEDA EXCEPTION HANDLER");

  if (i == 0)
    { P.text_item("\\bf Warning");
      P.text_item(string("%-64s",s));
      P.text_item("");
      P.button("continue");
      P.open();
     }
  else
    { P.text_item("\\bf Error");
      P.text_item(string("%-64s",s));
      P.text_item("");
      P.button("exit",0);
      P.button("core",1);
      if (P.open() == 0)
         quit_action(0);
      else 
         abort();
     }
 }



//------------------------------------------------------------------------------
// WINDOW OUTPUT
//------------------------------------------------------------------------------


// pixels

void window::draw_pix(double x, double y, color c ) 
{ BASE_WINDOW::draw_pix(x,y,c); }

void window::draw_pix(const point& p, color c ) 
{ draw_pix(p.xcoord(),p.ycoord(),c); }


void window::draw_pixels(const list<point>& L, color c ) 
{ int n = L.length();
  double* xcoord = new double[n];
  double* ycoord = new double[n];
  int i = 0;
  point p;
  forall(p,L)
  { xcoord[i] = p.xcoord();
    ycoord[i] = p.ycoord();
    i++;
   }

  BASE_WINDOW::draw_pixels(n,xcoord,ycoord,c);

  delete[] xcoord;
  delete[] ycoord;
}


void window::draw_pixels(int n, double* xcoord, double* ycoord, color c ) 
{ BASE_WINDOW::draw_pixels(n,xcoord,ycoord,c); }





void window::draw_text(double x, double y, string s, color c)
{ BASE_WINDOW::draw_text(x,y,s,c); }

void window::draw_text(const point& p, string s, color c)
{ draw_text(p.xcoord(),p.ycoord(),s,c); }

void window::draw_ctext(double x, double y, string s, color c)
{ BASE_WINDOW::draw_ctext(x,y,s,c); }

void window::draw_ctext(const point& p, string s, color c)
{ draw_ctext(p.xcoord(),p.ycoord(),s,c); }

void window::draw_ctext(string s, color c)
{ double x = (xmax() - xmin())/2;
  double y = (ymax() - ymin())/2;
  draw_ctext(x,y,s,c); 
}


// points

void window::draw_point(double x0,double y0,color c)
{ BASE_WINDOW::draw_point(x0,y0,c); }

void window::draw_point(const point& p,color c)
{ draw_point(p.xcoord(),p.ycoord(),c); }


// segments

void window::draw_segment(double x1, double y1, double x2, double y2, color c )
{ BASE_WINDOW::draw_segment(x1,y1,x2,y2,c); }

void window::draw_segment(const point& p, const point& q, color c )
{ window::draw_segment(p.xcoord(),p.ycoord(),q.xcoord(),q.ycoord(),c); }

void window::draw_segment(const segment& s, color c )
{ draw_segment(s.start(),s.end(),c); }

void window::draw_segments(const list<segment>& L, color c)
{ int n = L.length();
  double* xcoord1 = new double[n];
  double* ycoord1 = new double[n];
  double* xcoord2 = new double[n];
  double* ycoord2 = new double[n];

  int i = 0;
  segment s;
  forall(s,L)
  { xcoord1[i] = s.xcoord1();
    ycoord1[i] = s.ycoord1();
    xcoord2[i] = s.xcoord2();
    ycoord2[i] = s.ycoord2();
    i++;
   }

  BASE_WINDOW::draw_segments(n,xcoord1,ycoord1,xcoord2,ycoord2,c);

  delete[] xcoord1;
  delete[] ycoord1;
  delete[] xcoord2;
  delete[] ycoord2;
}


// lines

void window::draw_line(double x1, double y1, double x2, double y2, color c )
{ BASE_WINDOW::draw_line(x1,y1,x2,y2,c); }

void window::draw_line(const point& p, const point& q, color c )
{ window::draw_line(p.xcoord(),p.ycoord(),q.xcoord(),q.ycoord(),c); }

void window::draw_line(const segment& s, color c )
{ draw_line(s.start(),s.end(),c); }

void window::draw_line(const line& l, color c )
{ draw_line(l.seg(),c); }



void window::draw_hline(double y, color c )
{ BASE_WINDOW::draw_segment(xmin(),y,xmax(),y,c); }

void window::draw_vline(double x, color c )
{ BASE_WINDOW::draw_segment(x,ymin(),x,ymax(),c); }


// rays

void window::draw_ray(double x1, double y1, double x2, double y2, color c )
{ BASE_WINDOW::draw_ray(x1,y1,x2,y2,c); }

void window::draw_ray(const point& p, const point& q, color c )
{ window::draw_ray(p.xcoord(),p.ycoord(),q.xcoord(),q.ycoord(),c); }

void window::draw_ray(const segment& s, color c )
{ draw_ray(s.start(),s.end(),c); }

void window::draw_ray(const ray& l, color c )
{ draw_ray(l.seg(),c); }




// nodes

void window::draw_node(double x0,double y0,color c) 
{ BASE_WINDOW::draw_node(x0,y0,c); }

void window::draw_node(const point& p, color c)
{ window::draw_node(p.xcoord(),p.ycoord(),c); }

void window::draw_filled_node(double x0,double y0,color c)
{ BASE_WINDOW::draw_filled_node(x0,y0,c); }

void window::draw_filled_node(const point& p, color c)
{ window::draw_filled_node(p.xcoord(),p.ycoord(),c); }

void window::draw_text_node(double x,double y,string s,color c)
{ BASE_WINDOW::draw_text_node(x,y,~s,c); }

void window::draw_text_node(const point& p ,string s,color c)
{ window::draw_text_node(p.xcoord(),p.ycoord(),~s,c); }

void window::draw_int_node(double x,double y,int i,color c)
{ BASE_WINDOW::draw_int_node(x,y,i,c); }

void window::draw_int_node(const point& p ,int i,color c)
{ window::draw_int_node(p.xcoord(),p.ycoord(),i,c); }


//circles

void window::draw_circle(double x,double y,double r,color c)
{ BASE_WINDOW::draw_circle(x,y,r,c); }

void window::draw_circle(const point& p,double r,color c)
{ BASE_WINDOW::draw_circle(p.xcoord(),p.ycoord(),r,c); }

void window::draw_circle(const circle& C,color c)
{ point p = C.center();
  double r = C.radius();
  BASE_WINDOW::draw_circle(p.xcoord(),p.ycoord(),r,c); 
 }


// discs

void window::draw_disc(double x,double y,double r,color c)
{ BASE_WINDOW::draw_filled_circle(x,y,r,c); }

void window::draw_disc(const point& p,double r,color c)
{ window::draw_disc(p.xcoord(),p.ycoord(),r,c); }


void window::draw_disc(const circle& C,color c)
{ draw_disc(C.center(),C.radius(),c); }



//ellipses

void window::draw_ellipse(double x,double y,double r1,double r2,color c)
{ BASE_WINDOW::draw_ellipse(x,y,r1,r2,c); }

void window::draw_ellipse(const point& p, double r1, double r2, color c)
{ BASE_WINDOW::draw_ellipse(p.xcoord(),p.ycoord(),r1,r2,c); }

void window::draw_filled_ellipse(double x,double y,double r1,double r2,color c)
{ BASE_WINDOW::draw_filled_ellipse(x,y,r1,r2,c); }

void window::draw_filled_ellipse(const point& p, double r1, double r2, color c)
{ BASE_WINDOW::draw_filled_ellipse(p.xcoord(),p.ycoord(),r1,r2,c); }



// arcs

void window::draw_arc(const segment& s, double r, color col)
{ double d   = s.length()/(2*fabs(r));
  if (d > 1) return;
  double acd = acos(d);
  if (r < 0) 
    { point   m  = s.start().translate_by_angle(s.angle()-acd,-r);
      segment x(m,s.end());
      BASE_WINDOW::draw_arc(m.xcoord(),m.ycoord(),-r,-r,x.angle(),LEDA_PI-2*acd,col);
     }
  else 
    { point   m  = s.start().translate_by_angle(s.angle()+acd,r);
      segment x(m,s.end());
      BASE_WINDOW::draw_arc(m.xcoord(),m.ycoord(),r,r,x.angle(),2*acd-LEDA_PI,col);
     }
 }

void window::draw_arc(double x0,double y0,double x1,double y1,double r,color c)
{ draw_arc(segment(x0,y0,x1,y1),r,c); }

void window::draw_arc(const point& p, const point& q, double r, color c)
{ draw_arc(segment(p,q),r,c); }



void window::draw_arc_arrow(const segment& s, double r, color col)
{ double d   = s.length()/(2*r);
  if (d > 1) return;
  point p = draw_arrow_head(s.end(), s.angle() + LEDA_PI_2 - acos(d), col);
  draw_arc(s.start(),p,r,col);
 }

void window::draw_arc_arrow(double x0,double y0,double x1,double y1,double r,color c)
{ draw_arc_arrow(segment(x0,y0,x1,y1),r,c); }

void window::draw_arc_arrow(const point& p, const point& q, double r, color c)
{ draw_arc_arrow(segment(p,q),r,c); }


// polygons

void window::draw_polygon(const list<point>& lp, color c)
{ int n = lp.length();
  double* X = new double[n];
  double* Y = new double[n];
  n = 0;
  point p;
  forall(p,lp) 
  { X[n] = p.xcoord();
    Y[n] = p.ycoord();
    n++;
   }
  BASE_WINDOW::draw_polygon(n,X,Y,c);
  delete X;
  delete Y;
}

void window::draw_filled_polygon(const list<point>& lp, color c)
{ int n = lp.length();
  double* X = new double[n];
  double* Y = new double[n];
  n = 0;
  point p;
  forall(p,lp) 
  { X[n] = p.xcoord();
    Y[n] = p.ycoord();
    n++;
   }
  BASE_WINDOW::draw_filled_polygon(n,X,Y,c);
  delete X;
  delete Y;
}

void window::draw_polygon(const polygon& P, color c )
{ draw_polygon(P.vertices(),c); }

void window::draw_filled_polygon(const polygon& P,color c )
{ draw_filled_polygon(P.vertices(),c); }




void window::draw_rectangle(double x0,double y0,double x1,double y1, color col)
{ BASE_WINDOW::draw_rectangle(x0,y0,x1,y1,col); }

void window::draw_rectangle(point p, point q, color col)
{ BASE_WINDOW::draw_rectangle(p.xcoord(),p.ycoord(),q.xcoord(),q.ycoord(),col); }

void window::draw_filled_rectangle(double x0,double y0,double x1,double y1, color col)
{ BASE_WINDOW::draw_filled_rectangle(x0,y0,x1,y1,col); }

void window::draw_filled_rectangle(point p, point q, color col)
{ BASE_WINDOW::draw_filled_rectangle(p.xcoord(),p.ycoord(),q.xcoord(),q.ycoord(),col); }


void window::draw_triangle(point a, point b, point c, color col)
{ list<point> poly;
  poly.append(a);
  poly.append(b);
  poly.append(c);
  draw_polygon(poly,col);
}
   

void window::draw_filled_triangle(point a, point b, point c, color col)
{ list<point> poly;
  poly.append(a);
  poly.append(b);
  poly.append(c);
  draw_filled_polygon(poly,col);
}
   


// functions

void window::plot_xy(double x0, double x1, win_draw_func f, color c)
{ BASE_WINDOW::plot_xy(x0,x1,f,c); }

void window::plot_yx(double y0, double y1, win_draw_func f, color c)
{ BASE_WINDOW::plot_yx(y0,y1,f,c); }



// arrows

point window::draw_arrow_head(const point& q, double a, color c)
{ double X[4];
  double Y[4];
  
  double alpha = a-LEDA_PI; 

  //double d = 2*((get_line_width()+2)/3.0)/scale();

  double d = 2*((get_line_width()+1)/3.0)/scale();

  point l = q.translate_by_angle(alpha+LEDA_PI/6, 7*d);
  point m = q.translate_by_angle(alpha,           4*d);
  point r = q.translate_by_angle(alpha-LEDA_PI/6, 7*d);


  X[0] = q.xcoord();
  Y[0] = q.ycoord();
  X[1] = l.xcoord();
  Y[1] = l.ycoord();
  X[2] = m.xcoord();
  Y[2] = m.ycoord();
  X[3] = r.xcoord();
  Y[3] = r.ycoord();

  BASE_WINDOW::draw_filled_polygon(4,X,Y,c);
  return m;
}


void window::draw_arrow(const segment& s, color c)
{ point q = draw_arrow_head(s.end(),s.angle(),c);
  draw_segment(s.start(),q,c);
}

void window::draw_arrow(const point& p, const point& q, color c)
{ draw_arrow(segment(p,q),c); }

void window::draw_arrow(double x0, double y0, double x1, double y1, color c)
{ draw_arrow(segment(x0,y0,x1,y1),c); }





// edges

void window::draw_edge(double x0, double y0, double x1, double y1, color c)
{ BASE_WINDOW::draw_edge(x0,y0,x1,y1,c); }

void window::draw_edge(const point& p, const point& q, color c)
{ draw_edge(p.xcoord(),p.ycoord(),q.xcoord(),q.ycoord(),c); }

void window::draw_edge(const segment& s, color c)
{ draw_edge(s.start(),s.end(),c); }


void window::draw_arc_edge(double x0, double y0, double x1, double y1, double r, color c)
{ draw_arc_edge(segment(x0,y0,x1,y1),r,c); }

void window::draw_arc_edge(const point& p, const point& q, double r, color c)
{ draw_arc_edge(segment(p,q),r,c); }

void window::draw_arc_edge(const segment& s, double r, color c)
{ double R = get_node_width()/scale();
  double d = s.length()/(2*r);
  if (d > 1) return;
  point p = s.start().translate_by_angle(s.angle() - LEDA_PI_2 + acos(d), R);
  point q = s.end().translate_by_angle(s.angle() + LEDA_PI_2 - acos(d),  -R);
  draw_arc(p,q,r,c);
 }


void window::draw_edge_arrow(double x0,double y0,double x1,double y1,color c)
{ draw_edge_arrow(segment(x0,y0,x1,y1),c); }

void window::draw_edge_arrow(const point& p, const point& q, color c)
{ draw_edge_arrow(segment(p,q),c); }

void window::draw_edge_arrow(const segment& s, color c)
{ double  alpha = s.angle();
  point p = s.start().translate_by_angle(alpha,get_node_width()/scale());
  point q = s.end().translate_by_angle(alpha,-get_node_width()/scale());
  draw_arrow(p,q,c);
}



void window::draw_arc_edge_arrow(double x,double y,double x1,double y1, double r, color c)
{ draw_arc_edge_arrow(segment(x,y,x1,y1),r, c); }

void window::draw_arc_edge_arrow(const point& p, const point& q, double r, color c)
{ draw_arc_edge_arrow(segment(p,q),r,c); }

void window::draw_arc_edge_arrow(const segment& s, double r, color c)
{ double R = get_node_width()/scale();
  double d = s.length()/(2*r);
  if (d > 1) return;
  point p = s.start().translate_by_angle(s.angle() - LEDA_PI_2 + acos(d), R);
  point q = s.end().translate_by_angle(s.angle() + LEDA_PI_2 - acos(d),  -R);
  draw_arc_arrow(p,q,r,c);
 }


//------------------------------------------------------------------------------
// WINDOW INPUT
//------------------------------------------------------------------------------


int window::get_mouse() 
{ return BASE_WINDOW::get_mouse(); }

int window::get_mouse(double& x, double& y) 
{ return BASE_WINDOW::get_mouse(x,y); }

int  window::get_mouse(point& q)
{ double x,y;
  int key = BASE_WINDOW::get_mouse(x,y);
  q = point(x,y);
  return key;
 }


int window::read_mouse() 
{ return BASE_WINDOW::read_mouse(); }

int  window::read_mouse(double& x, double& y)
{ return BASE_WINDOW::read_mouse(0,0.0,0.0,x,y); }

int  window::read_mouse(point& q)
{ double x,y;
  int key = BASE_WINDOW::read_mouse(0,0.0,0.0,x,y);
  q = point(x,y);
  return key;
 }


int  window::read_mouse_seg(double x0, double y0, double& x, double& y)
{ return BASE_WINDOW::read_mouse(1,x0,y0,x,y); }

int  window::read_mouse_seg(const point& p, point& q)
{ double X,Y;
  int key = BASE_WINDOW::read_mouse(1,p.xcoord(),p.ycoord(),X,Y);
  q = point(X,Y);
  return key;
}


int  window::read_mouse_rect(double x0, double y0, double& x, double& y)
{ return BASE_WINDOW::read_mouse(2,x0,y0,x,y); }


int  window::read_mouse_rect(const point& p, point& q)
{ double X,Y;
  int key = BASE_WINDOW::read_mouse(2,p.xcoord(),p.ycoord(),X,Y);
  q = point(X,Y);
  return key;
}


int  window::read_mouse_circle(double x0, double y0, double& x, double& y)
{ return BASE_WINDOW::read_mouse(3,x0,y0,x,y); }


int  window::read_mouse_circle(const point& p, point& q)
{ double X,Y;
  int key = BASE_WINDOW::read_mouse(3,p.xcoord(),p.ycoord(),X,Y);
  q = point(X,Y);
  return key;
}



int window::read_mouse_action(mouse_action_func f, double& x, double& y)
{ return BASE_WINDOW::read_mouse_action(f,0.0,0.0,x,y); }


int window::read_mouse_action(mouse_action_func f, point& q)
{ double X,Y;
  int key = BASE_WINDOW::read_mouse_action(f,0.0,0.0,X,Y);
  q = point(X,Y);
  return key;
}



window& window::read(point& p)
{ double x,y;
  state = 1;
  int save_but[8];
  std_buttons(save_but);
  if (read_mouse(x,y) == MOUSE_BUTTON(1)) 
     p = point(x,y);
  else
     state = 0;
  set_buttons(save_but);
  return *this;
 }


window& window::read(segment& s)
{ double x,y;
  point p;
  int key = 0;
  state = 1;

  int save_but[8];
  std_buttons(save_but);

  if (!read(p).state) return *this;

  while ((key=read_mouse_seg(p.xcoord(),p.ycoord(),x,y)) != MOUSE_BUTTON(1))
  { if (key == MOUSE_BUTTON(3))  
     { state = 0;
       break; 
      }

    if (key == MOUSE_BUTTON(1) && shift_key_down())
      if (!read(p).state) break;
   }

   if (state) s = segment(p.xcoord(),p.ycoord(),x,y);

  set_buttons(save_but);
  return *this;
}


window& window::read(ray& l)
{ segment s;
  state = 1;
  read(s);
  if (state) l = ray(s);
  return *this;
 }


window& window::read(line& l)
{ segment s;
  state = 1;
  read(s);
  if (state) l = line(s);
  return *this;
 }


window& window::read(circle& c)
{ double x,y;
  point p;
  int key = 0;
  state = 1;

  if (!read(p).state) return *this;

  int save_but[8];
  std_buttons(save_but);

  drawing_mode save = set_mode(xor_mode);
  draw(p);

  while ((key=read_mouse_circle(p.xcoord(),p.ycoord(),x,y)) != MOUSE_BUTTON(1))
  { if (key == MOUSE_BUTTON(3))  
     { state = 0;
       break; 
      }

    if (key == MOUSE_BUTTON(1) && shift_key_down())
    { draw(p);
      if (!read(p).state) break;
      draw(p);
     }
   }
   if (state) 
   { double dx = x-p.xcoord();
     double dy = y-p.ycoord();
     c = circle(p,sqrt(dx*dx+dy*dy));
     draw(p);
    }

  set_mode(save);
  set_buttons(save_but);
  return *this;
}

window& window::read(polygon& P)
{ double x,y;
  int key = 0;
  state = 1;
  point first,last,p;
  list<point> pl;

  if (!read(first).state) 
  { P = pl;
    return *this;
   }


  int save_but[8];
  std_buttons(save_but);

  pl.append(first);

  p = first;

  drawing_mode save = set_mode(xor_mode);

  while ((key = read_mouse_seg(p.xcoord(),p.ycoord(),x,y)) == MOUSE_BUTTON(1))
  { 
    if (!shift_key_down()) 
      { point q(x,y);
        draw_segment(p,q);
        pl.append(q);
        p = q;
       }
     else 
       if (pl.length() > 1 ) 
       { point l = pl.Pop();
         draw_segment(pl.tail(),l);
         p = pl.tail();
        }
  }

  draw_segment(first,p);

  list_item it;
  forall_items(it,pl) draw_segment(pl[it],pl[pl.cyclic_succ(it)]);

  P = polygon(pl);

  set_mode(save);
  set_buttons(save_but);
  return *this;

}


window& window::operator>>(point& p)    
{ set_frame_label(">> POINT");
  read(p); 
  reset_frame_label();
  return *this; 
 }

window& window::operator>>(segment& s)  
{ set_frame_label(">> SEGMENT");
  read(s); 
  reset_frame_label();
  return *this; 
 }


window& window::operator>>(ray& r)  
{ set_frame_label(">> RAY");
  read(r); 
  reset_frame_label();
  return *this; 
 }

window& window::operator>>(line& l)     
{ set_frame_label(">> LINE");
  read(l); 
  reset_frame_label();
  return *this; 
 }

window& window::operator>>(circle& C)   
{ set_frame_label(">> CIRCLE");
  read(C); 
  reset_frame_label();
  return *this; 
 }

window& window::operator>>(polygon& P)  
{ set_frame_label(">> POLYGON");
  read(P); 
  reset_frame_label();
  return *this; 
 }




bool window::confirm(string s)
{ panel p;
  p.text_item(s);
  p.button("YES",1);
  p.button("NO",0);
  return p.open(*this);
}


void window::acknowledge(string s)
{ panel p("ACKNOWLEDGE");
  p.text_item(s);
  p.button("ok");
  p.open(*this);
}

void window::notice(string s)
{ panel p("NOTICE");
  p.text_item(s);
  p.button("ok");
  p.open(*this);
}


int  window::read_panel(string header, int n, string* L)
{ panel P("LEDA PANEL");
  P.text_item(header);
  for(int i = 0; i < n; i++) P.button(L[i]);
  return P.open(*this);
 }


int  window::read_vpanel(string header, int n, string* L)
{ panel P("LEDA PANEL");
  P.buttons_per_line(1);
  P.text_item(header);
  for(int i = 0; i < n; i++)  P.button(L[i]);
  return P.open(*this);
 }


string  window::read_string(string prompt)
{ panel P("STRING INPUT PANEL");
  string s;
  P.string_item(prompt,s);
  P.open(*this);
  return s;
 }

int  window::read_int(string prompt)
{ panel P("INT INPUT PANEL");
  int i = 0;
  P.int_item(prompt,i);
  P.open(*this);
  return i;
}

double  window::read_real(string prompt)
{ panel P("DOUBLE INPUT PANEL");
  double x = 0;
  P.real_item(prompt,x);
  P.open(*this);
  return x;
 }



//------------------------------------------------------------------------------
//   PANEL OPERATIONS
//------------------------------------------------------------------------------


int window::button(string s, const char* hlp)   
{ panel_action_func f= 0;
  return BASE_WINDOW::button(s,-1,f,hlp); }

int window::button(int w, int h, char* bm, string s, const char* hlp)
{ panel_action_func f= 0;
  return BASE_WINDOW::button(w,h,bm,s,-1,f,hlp); }


int window::button(string s,int v, const char* hlp)  
{ panel_action_func f= 0;
  return BASE_WINDOW::button(s,v,f,hlp); }

int window::button(int w, int h, char* bm, string s, int v, const char* hlp)
{ panel_action_func f= 0;
  return BASE_WINDOW::button(w,h,bm,s,v,f,hlp); }


int window::button(string s, panel_action_func F, const char* hlp)   
{ return BASE_WINDOW::button(s,-1,F,hlp); }

int window::button(int w, int h, char* bm, string s, panel_action_func F, 
                                                     const char* hlp)   
{ return BASE_WINDOW::button(w,h,bm,s,-1,F,hlp); }


int window::button(string s, int v, panel_action_func F, const char* hlp)   
{ return BASE_WINDOW::button(s,v,F,hlp); }

int window::button(int w, int h, char* bm, string s, int v, panel_action_func F,
                                                            const char* hlp)
{ return BASE_WINDOW::button(w,h,bm,s,v,F,hlp); }


int window::button(string s, window& p, const char* hlp)   
{ return BASE_WINDOW::button(s,-2,(BASE_WINDOW*)&p,hlp); }

int window::button(int w, int h, char* bm, string s, window& p, const char* hlp)
{ return BASE_WINDOW::button(w,h,bm,s,-2,(BASE_WINDOW*)&p,hlp); }


int window::button(string s, int val, window& p, const char* hlp)   
{ return BASE_WINDOW::button(s,val,(BASE_WINDOW*)&p,hlp); }

int window::button(int w, int h, char* bm, string s, int val, window& p,
                                                              const char* hlp)
{ return BASE_WINDOW::button(w,h,bm,s,val,(BASE_WINDOW*)&p,hlp); }


int window::menu_button(string s, int val, window& p, const char* hlp)   
{ return BASE_WINDOW::menu_button(s,val,(BASE_WINDOW*)&p,hlp); }

int window::menu_button(string s, window& p, const char* hlp)   
{ return BASE_WINDOW::menu_button(s,-2,(BASE_WINDOW*)&p,hlp); }




window* window::get_window(string s)
{ return (window*)BASE_WINDOW::get_window(s.cstring()); }

window* window::set_window(string s, window* M)
{ return (window*)BASE_WINDOW::set_window(s.cstring(), M); }



panel_item window::text_item(string s)   
{ return BASE_WINDOW::text_item(s); }

panel_item window::int_item(string s,int& x,const char* hlp) 
{ return BASE_WINDOW::int_item(s,&x,hlp);}

panel_item window::int_item(string s,int& x, int l, int h,const char* hlp) 
{ return BASE_WINDOW::slider_item(s,&x,l,h,0,hlp);}

panel_item window::int_item(string s,int& x, int l, int h, void (*F)(int),const char* hlp) 
{ return BASE_WINDOW::slider_item(s,&x,l,h,F,hlp);}

panel_item window::double_item(string s, double& x,const char* hlp) 
{ return BASE_WINDOW::float_item(s,&x,hlp);}

panel_item window::real_item(string s, double& x,const char* hlp)
{ return BASE_WINDOW::float_item(s,&x,hlp); }

panel_item window::string_item(string label, string& x,const char* hlp)
{ x = ~x; //disconnect
  return BASE_WINDOW::string_item(label,&x,0,hlp);
 }

panel_item window::string_item(string label, string& x, void (*F)(char*), 
                                                        const char* hlp)
{ x = ~x; //disconnect
  return BASE_WINDOW::string_item(label,&x,F,hlp);
 }


panel_item  window::string_item(string label,string& x, const list<string>& L,
                                const char* hlp)
{ return string_item(label,x,L,0,hlp); }

panel_item  window::string_item(string label,string& x, const list<string>& L,
                                void (*F)(char*), const char* hlp)
{ x = x.cstring(); //disconnect
  const char** p = new const char*[L.length()];
  int    i = 0;
  string s;
  forall(s,L) 
     if (s.length() > 0) p[i++] = s;
  panel_item it = BASE_WINDOW::string_menu_item(label,&x,"",i,p,F,hlp); 
  delete[] p;
  return it;
}

void window::add_menu(panel_item it, const list<string>& L)
{ const char** argv = new const char*[L.length()];
  int argc = 0;
  string s;
  forall(s,L) 
     if (s.length() > 0) argv[argc++] = s;
  BASE_WINDOW::add_menu(it,argc,argv); 
  delete[] argv;
}



// choice items

panel_item  window::choice_item(string label,int& x, const list<string>& L,
                                void (*F)(int), const char* hlp)
{ const char** p = new const char*[L.length()];
  int    i = 0;
  string s;
  forall(s,L) p[i++] = s;
  panel_item it = BASE_WINDOW::choice_item(label,&x,i,p,1,0,F,hlp); 
  delete[] p;
  return it;
}

panel_item  window::choice_mult_item(string label,int& x, const list<string>& L,const char* hlp)
{ return choice_mult_item(label,x,L,0,hlp); }

panel_item  window::choice_mult_item(string label,int& x, const list<string>& L,
                                                    void (*F)(int),const char* hlp)
{ const char** p = new const char*[L.length()];
  int    i = 0;
  string s;
  forall(s,L) p[i++] = s;
  panel_item it = BASE_WINDOW::choice_mult_item(label,&x,i,p,F,hlp); 
  delete[] p;
  return it;
}


// bitmap choice item

panel_item window::choice_item(string label, int& x, int n, int w, int h, 
                               char** bm,const char* hlp) 
{ return BASE_WINDOW::bitmap_choice_item(label,&x,n,w,h,bm,0,hlp); }

panel_item window::choice_item(string label, int& x, int n, int w, int h, 
                               char** bm, void (*F)(int),const char* hlp) 
{ return BASE_WINDOW::bitmap_choice_item(label,&x,n,w,h,bm,F,hlp); }



panel_item window::choice_mult_item(string label, int& x, int n, int w, int h, 
                                    char** bm, const char* hlp) 
{ return BASE_WINDOW::bitmap_choice_mult_item(label,&x,n,w,h,bm,0,hlp); }

panel_item window::choice_mult_item(string label, int& x, int n, int w, int h, 
                                    char** bm, void (*F)(int),const char* hlp) 
{ return BASE_WINDOW::bitmap_choice_mult_item(label,&x,n,w,h,bm,F,hlp); }



panel_item  window::choice_item(string label,int& x,const char* hlp,int n, ...)
{ const char* p[32];
  va_list arg_list;
  va_start(arg_list,n);
  for(int i=0; i<n; i++)
    p[i] = va_arg(arg_list,char*);
  va_end(arg_list);
  return BASE_WINDOW::choice_item(label,&x,n,p,1,0,0,hlp);
 }

panel_item  window::choice_item(string label,int& x,char* s1, char* s2, const char* hlp)
{ return choice_item(label,x,hlp,2,s1,s2); }

panel_item  window::choice_item(string label,int& x,char* s1, char* s2, char* s3, const char* hlp)
{ return choice_item(label,x,hlp,3,s1,s2,s3); }

panel_item  window::choice_item(string label,int& x,char* s1, char* s2, char* s3, char* s4, const char* hlp)
{ return choice_item(label,x,hlp,4,s1,s2,s3,s4); }

panel_item  window::choice_item(string label,int& x,char* s1, char* s2, char* s3, char* s4, char* s5, const char* hlp)
{ return choice_item(label,x,hlp,5,s1,s2,s3,s4,s5); }

panel_item  window::choice_item(string label,int& x,char* s1, char* s2, char* s3, char* s4, char* s5, char* s6, const char* hlp)
{ return choice_item(label,x,hlp,6,s1,s2,s3,s4,s5,s6); }

panel_item  window::choice_item(string label,int& x,char* s1, char* s2, char* s3, char* s4, char* s5, char* s6, char* s7, const char* hlp)
{ return choice_item(label,x,hlp,7,s1,s2,s3,s4,s5,s6,s7); }

panel_item  window::choice_item(string label,int& x,char* s1, char* s2, char* s3, char* s4, char* s5, char* s6, char* s7, char* s8, const char* hlp)
{ return choice_item(label,x,hlp,8,s1,s2,s3,s4,s5,s6,s7,s8); }



panel_item window::int_item(string s,int& x,int low, int high, int step,const char* hlp)   
{ return int_item(s,x,low,high,step,0,hlp); }


panel_item window::int_item(string s,int& x,int low, int high, int step,
                                            void (*F)(int), const char* hlp)   
{ int n = (high-low)/step +1;
  char** p = new char*[n];
  for(int i = 0; i < n; i++) 
  { p[i] =  new char[16];
    sprintf(p[i],"%d",low+i*step);
   }
  panel_item it = 
   BASE_WINDOW::choice_item(s,&x,n,(const char**)p,step,low,F,hlp);
  for(int j = 0; j < n; j++)  delete[] p[j];
  delete p;
  return it;
 }


panel_item window::bool_item(string s, bool& x,void (*F)(int),const char* hlp)
{ return BASE_WINDOW::bool_item(s,(char*)&x,F,hlp); }

panel_item window::bool_item(string s, bool& x,const char* hlp)
{ return BASE_WINDOW::bool_item(s,(char*)&x,0,hlp); }


panel_item window::color_item(string s, color& x,const char* hlp)
{ return BASE_WINDOW::color_item(s,(int*)&x,0,hlp); }

panel_item window::color_item(string s, color& x,void (*F)(int),const char* hlp)
{ return BASE_WINDOW::color_item(s,(int*)&x,F,hlp); }

panel_item window::lstyle_item(string s, line_style& x,const char* hlp)
{ const char* p[3];

  p[0] = "solid";
  p[1] = "dashed";
  p[2] = "dotted";

  return BASE_WINDOW::choice_item(s,(int*)&x,3,p,1,0,0,hlp);
 }


