PROGRAM(widget);
// The basic widget, inherited (directly or indirectly) by all
// widgets.  Thus, all functions and signals defined in this widget
// works on all widgets.
SIGNAL("show", "Called when the widget is shown");
SIGNAL("hide", "Called when the widget is hidden");
SIGNAL("map",  "Called when the window associated with the widget is mapped");
SIGNAL("unmap", "Called when the window associated with the widget is unmapped");
SIGNAL("realize", "");
SIGNAL("unrealize", "");
SIGNAL("draw", "");
SIGNAL("draw_focus", "");
SIGNAL("draw_default", "");
SIGNAL("add_accelerator", "");
SIGNAL("remove_accelerator", "");
SIGNAL("size_request", "");
SIGNAL("size_allocate", "");
SIGNAL("state_changed", "");
SIGNAL("parent_set", "");
SIGNAL("style_set", "");
SIGNAL("event", "Called for all events");
SIGNAL("button_press_event", "");
SIGNAL("button_release_event", "");
SIGNAL("motion_notify_event", "");
SIGNAL("delete_event",  "");
SIGNAL("destroy_event", "");
SIGNAL("expose_event",  "");
SIGNAL("key_press_event", "");
SIGNAL("key_release_event", "");
SIGNAL("enter_notify_event", "");
SIGNAL("leave_notify_event", "");
SIGNAL("configure_event", "");
SIGNAL("focus_in_event", "");
SIGNAL("focus_out_event", "");
SIGNAL("map_event", "");
SIGNAL("unmap_event", "");
SIGNAL("property_notify_event", "");
SIGNAL("selection_clear_event", "");
SIGNAL("selection_request_event", "");
SIGNAL("selection_notify_event", "");
SIGNAL("selection_received", "");
SIGNAL("proximity_in_event", "");
SIGNAL("proximity_out_event", "");
SIGNAL("drag_begin_event", "");
SIGNAL("drag_request_event", "");
SIGNAL("drag_end_event", "");
SIGNAL("drop_enter_event", "");
SIGNAL("drop_leave_event", "");
SIGNAL("drop_data_available_event", "");
SIGNAL("other_event", "");
SIGNAL("client_event", "");
SIGNAL("no_expose_event", "");
INHERIT(object);
/*  TODO: Many functions left to implement */
SIMPLE_FUNCTION(show);
// Show the widget. Most (almost all) widgets must be shown to be
// visible on the screen.

SUBWIDGET(parent,widget);
// Returns the parent of this widget, if any, if there is no parent
// 0 is returned.

FUNCTION(text_width, "function(string:int)");
NAME_ARGS(text);
// Returns the width, in pixels, the string would have if it was
// written with the default font in the style object assosiated with
// the widget. Currently, this is always a 8bit string, but that
// should hopefully change in the future. 
{
  struct pike_string *s;
  get_all_args("text_width", args, "%S", &s); 
  push_int(gdk_text_width(GTK_WIDGET( THIS->obj )->style->font,s->str,s->len));
}


#define TWIN  (GTK_WIDGET(THIS->obj)->window)
#define GC(X) ((GdkGC*)get_gdkobject(X,GC))

FUNCTION(set_background, "function(object:object)");
NAME_ARGS(background);
// Set the background color or image.
// The argument is either a GDK.Pixmap or a GDK.Color object.
{
  struct object *o;
  get_all_args("set_background", args, "%o", &o);

  if(get_gdkobject(o,Pixmap))
    gdk_window_set_back_pixmap(TWIN,
			       get_gdkobject(o,Pixmap), 0);
  else if(get_gdkobject(o,Color))
    gdk_window_set_background(TWIN, get_gdkobject(o,Color));

  RETURN_THIS();
}

FUNCTION(copy_area, "function(object,int,int,object,int,int,int,int:object)");
RETURNS(GDK.Widget);
ARGS(GDK.GC,int,int,GTK.Widget,int,int,int,int);
NAME_ARGS(gc,xdest,ydest,source,xsource,ysource,width,height);
// Copies the rectangle defined by xsource,ysource and width,height
// from the source widget, and places the results at xdest,ydest in
// the widget in which this function is called. 
{
  struct object *gc, *source;
  GdkWindow *win;
  int xd, yd, xs, ys, w, h;
  get_all_args("copy_area",args, "%o%d%d%o%d%d%d%d", 
	       &gc, &xd, &yd, &source, &xs, &ys, &w, &h);

  if(get_gdkobject( source, Drawable ))
    win = get_gdkobject( source, Drawable );
  else
    win = GTK_WIDGET( get_gtkobject( source ) )->window;

  gdk_window_copy_area( GTK_WIDGET( THIS->obj )->window, 
			GC(gc), xd, yd, win, xs, ys, w, h);
  RETURN_THIS();
}

FUNCTION(shape_combine_mask, "function(object,int,int:object)");
RETURNS(GTK.Widget);
ARGS(GDK.Bitmap,xoffset,yoffset);
// Set the shape of the widget, or, rather, it's window, to that of
// the supplied bitmap. Notice how the window behind the example
// window can be seen because of the rather odd shape the example window has.

// TIMG: GTK.Window( GTK.WINDOW_TOPLEVEL )->add(GTK.Label("A rather Oddly shaped\n" "Window\n" "Indeed\n" "Or what do you\nthink?\n" "This text\n" "should\n" "be long enough")->show())->show()->shape_combine_mask( GDK.Bitmap(Image.image(100,100,255,255,255)->rotate(10,0,0,0) ), 20,20)
{
  struct object *m;
  int x, y;
  get_all_args("shape_combine", args, "%o%d%d", &m, &x, &y);
  gtk_widget_shape_combine_mask( GTK_WIDGET( THIS->obj ),
				 get_gdkobject(m,Bitmap), x, y);
  RETURN_THIS();
}

FUNCTION(xoffset, "function(void:int)")
// Returns the x position of the upper left corner relative to the
// widgets window in pixels. For widgets that have their own window
// this will most likely be 0.
{
  push_int( GTK_WIDGET( THIS->obj )->allocation.x );
}

FUNCTION(yoffset, "function(void:int)")
// Returns the y position of the upper left corner relative to the
// widgets window in pixels. For widgets that have their own window
// this will most likely be 0.
{
  push_int( GTK_WIDGET( THIS->obj )->allocation.y );
}

FUNCTION(xsize, "function(void:int)")
// Returns the width of the widget in pixels.
{
  push_int( GTK_WIDGET( THIS->obj )->allocation.width );
}

FUNCTION(ysize, "function(void:int)")
// Returns the height of the widget in pixels.
{
  push_int( GTK_WIDGET( THIS->obj )->allocation.height );
}

FUNCTION(allocation, "function(void:mapping)");
{
  push_text( "x" );
  push_int( GTK_WIDGET( THIS->obj )->allocation.x );
  push_text( "y" );
  push_int( GTK_WIDGET( THIS->obj )->allocation.y );
  push_text( "width" );
  push_int( GTK_WIDGET( THIS->obj )->allocation.width );
  push_text( "height" );
  push_int( GTK_WIDGET( THIS->obj )->allocation.height );
  f_aggregate_mapping( 8 );
}

COMPLEX_FUNCTION(add_accelerator, string, accel_group, int, int, int);
NAME_ARGS(signal, table, key, modifiers, flags);
// Flage is one of CONST(GTK_ACCE)
COMPLEX_FUNCTION(remove_accelerator, accel_group, int, int);
NAME_ARGS(table,key,modifiers);
COMPLEX_FUNCTION(set_usize, int, int);
NAME_ARGS(xsize,ysize);
// Set the absolute size of the widget. It might resize itself anyway,
// but this size is used as is in most widgets. Beware of this
// function, it might produce unexpected results.
COMPLEX_FUNCTION(set_uposition, int, int);
NAME_ARGS(xpos,ypos);
// Set the absolute coordinates of the widget. For most widgets these
// are 0,0
COMPLEX_FUNCTION(set_name, string);
NAME_ARGS(name);
// Set the name of the widget. The name is used when the rc-file is
// parsed, you can also parse your own resources by calling
// GTK.parse_rc() with a resource string. <br>Example: <p>
// TODO
COMPLEX_FUNCTION(set_state, int);
NAME_ARGS(state);
// One of CONST(GTK_STATE)
COMPLEX_FUNCTION(set_sensitive, int);
NAME_ARGS(sensitivep);
// True (1) or fals (0). If true, the widget can receive events,
// otherwise the user cannot interact with the widget. Most widgets
// are drawn 'greyed' or more dim when they are unsensitive.
string COMPLEX_FUNCTION(get_name);
// Returns the name set by set_name or the class name
FUNCTION(set_cursor, "function(int:object)");
NAME_ARGS(cursor_type);
// One of GDK.Arrow, GDK.BasedArrowDown, GDK.BasedArrowUp, GDK.Boat,
// GDK.Bogosity, GDK.BottomLeftCorner, GDK.BottomRightCorner,
// GDK.BottomSide, GDK.BottomTee, GDK.BoxSpiral, GDK.CenterPtr,
// GDK.Circle, GDK.Clock, GDK.CoffeeMug, GDK.Cross, GDK.CrossReverse,
// GDK.Crosshair, GDK.DiamondCross, GDK.Dot, GDK.Dotbox,
// GDK.DoubleArrow, GDK.DraftLarge, GDK.DraftSmall, GDK.DrapedBox,
// GDK.Exchange, GDK.Fleur, GDK.Gobbler, GDK.Gumby, GDK.Hand1,
// GDK.Hand2, GDK.Heart, GDK.Icon, GDK.IronCross, GDK.LeftPtr,
// GDK.LeftSide, GDK.LeftTee, GDK.Leftbutton, GDK.LlAngle,
// GDK.LrAngle, GDK.Man, GDK.Middlebutton, GDK.Mouse, GDK.Pencil,
// GDK.Pirate, GDK.Plus, GDK.QuestionArrow, GDK.RightPtr,
// GDK.RightSide, GDK.RightTee, GDK.Rightbutton, GDK.RtlLogo,
// GDK.Sailboat, GDK.SbDownArrow, GDK.SbHDoubleArrow, GDK.SbLeftArrow,
// GDK.SbRightArrow, GDK.SbUpArrow, GDK.SbVDoubleArrow, GDK.Shuttle,
// GDK.Sizing, GDK.Spider, GDK.Spraycan, GDK.Star, GDK.Target,
// GDK.Tcross, GDK.TopLeftArrow, GDK.TopLeftCorner,
// GDK.TopRightCorner, GDK.TopSide, GDK.TopTee, GDK.Trek, GDK.UlAngle,
// GDK.Umbrella, GDK.UrAngle, GDK.Watch and GDK.Xterm
{
  GdkCursor *c;
  static GdkCursor *font_cursors[ 256 ];
  int i;

  get_all_args("set_cursor", args, "%d", &i);

  if(i>255) 
    error("No such cursor\n");

  if(font_cursors[ i ])
    c = font_cursors[ i ];
  else
    c = font_cursors[ i ] = gdk_cursor_new( i );
  gdk_window_set_cursor( GTK_WIDGET( THIS->obj )->window, c );

  RETURN_THIS();
}
FUNCTION(set_bitmap_cursor, "function(object,object,object,object,int,int:object)");

ARGS(GDK.Bitmap,GDK.Bitmap,GDK.Color,GDK.Color,int,int);
NAME_ARGS(source,mask,fg,bg,xhot,yhot);
// xhot,yhot are the locations of the x and y hotspot relative to the
// upper left corner of the cursor image.
{
  struct object *s, *m, *fg, *bg;
  int xh, yh;
  get_all_args("set_bitmap_cursor", args, "%o%o%o%o%d%d", 
	       &s,&m,&fg,&bg,&xh,&yh);
  gdk_window_set_cursor( GTK_WIDGET( THIS->obj )->window,
			 gdk_cursor_new_from_pixmap( get_gdkobject( s, Pixmap ),
						     get_gdkobject( m, Bitmap ),
						     get_gdkobject( fg, Color),
						     get_gdkobject( bg, Color ),
						     xh,yh ) );
  RETURN_THIS();
}
SIMPLE_FUNCTION(unparent);
SIMPLE_FUNCTION(realize);
SIMPLE_FUNCTION(unrealize);
SIMPLE_FUNCTION(queue_draw);
COMPLEX_FUNCTION(queue_draw_area, int,int,int,int);
NAME_ARGS(x,y,width,height);
SIMPLE_FUNCTION(queue_clear);
COMPLEX_FUNCTION(queue_clear_area, int,int,int,int);
NAME_ARGS(x,y,width,height);
SIMPLE_FUNCTION(ensure_style);
SIMPLE_FUNCTION(queue_resize);
SIMPLE_FUNCTION(show_now);
// Show this widget and do not return until it is visible.
SIMPLE_FUNCTION(hide);
// Hide this widget
SIMPLE_FUNCTION(show_all);
// Show this widget and all children
SIMPLE_FUNCTION(hide_all);
// Hide this widget and all children
SIMPLE_FUNCTION(map);
SIMPLE_FUNCTION(unmap);
SIMPLE_FUNCTION(activate);
/* SIMPLE_FUNCTION(basic); */
SIMPLE_FUNCTION(grab_focus);
SIMPLE_FUNCTION(grab_default);
int COMPLEX_FUNCTION(intersect, GdkRectangle,GdkRectangle);
NAME_ARGS(area,intersection);
COMPLEX_FUNCTION(reparent, widget);
COMPLEX_FUNCTION(popup, int,int);
NAME_ARGS(xpos,ypos);
COMPLEX_FUNCTION(add_events, int);
NAME_ARGS(events);
// Events is one or more of:
// GDK.ExposureMask, GDK.PointerMotionMask,
// GDK.PointerMotion_HINTMask, GDK.ButtonMotionMask,
// GDK.Button1MotionMask, GDK.Button2MotionMask,
// GDK.Button3MotionMask, GDK.ButtonPressMask, GDK.ButtonReleaseMask,
// GDK.KeyPressMask, GDK.KeyReleaseMask, GDK.EnterNotifyMask,
// GDK.LeaveNotifyMask, GDK.FocusChangeMask, GDK.StructureMask,
// GDK.PropertyChangeMask, GDK.VisibilityNotifyMask,
// GDK.ProximityInMask, GDK.ProximityOutMask and GDK.AllEventsMask

COMPLEX_FUNCTION(set_events, int);
NAME_ARGS(events);
// Events is one or more of:
// GDK.ExposureMask, GDK.PointerMotionMask,
// GDK.PointerMotion_HINTMask, GDK.ButtonMotionMask,
// GDK.Button1MotionMask, GDK.Button2MotionMask,
// GDK.Button3MotionMask, GDK.ButtonPressMask, GDK.ButtonReleaseMask,
// GDK.KeyPressMask, GDK.KeyReleaseMask, GDK.EnterNotifyMask,
// GDK.LeaveNotifyMask, GDK.FocusChangeMask, GDK.StructureMask,
// GDK.PropertyChangeMask, GDK.VisibilityNotifyMask,
// GDK.ProximityInMask, GDK.ProximityOutMask and GDK.AllEventsMask
COMPLEX_FUNCTION(set_extension_events, int);
NAME_ARGS(events);
// Events is one of CONST(GDK_EXTENSION_EVENT)
int COMPLEX_FUNCTION(get_extension_events);
// Returns one of CONST(GDK_EXTENSION_EVENT)

/* TODO; GdkWindow COMPLEX_FUNCTION(get_parent_window); */
/* TODO: Widget COMPLEX_FUNCTION(get_ancestor, int);  argument is widgettype*/
Widget COMPLEX_FUNCTION(get_toplevel);
int COMPLEX_FUNCTION(get_events);
int COMPLEX_FUNCTION(is_ancestor, widget);
Style COMPLEX_FUNCTION(get_style);
COMPLEX_FUNCTION(restore_default_style);
COMPLEX_FUNCTION(reset_rc_styles);
COMPLEX_FUNCTION(set_composite_name, string);
string COMPLEX_FUNCTION(get_composite_name);

FUNCTION(path, "function(void:string)");
{
  gchar *path, *prev;
  guint path_length;
  
  gtk_widget_path( GTK_WIDGET( THIS->obj ), &path_length, &path, &prev );

  push_text( path );
  g_free(path);
  g_free(prev);
}

FUNCTION(class_path, "function(void:string)");
{
  gchar *path, *prev;
  guint path_length;

  gtk_widget_class_path( GTK_WIDGET( THIS->obj ), &path_length, &path, &prev );

  push_text( path );
  g_free(path);
  g_free(prev);
}

COMPLEX_FUNCTION(lock_accelerators);
COMPLEX_FUNCTION(unlock_accelerators);

int COMPLEX_FUNCTION(set_scroll_adjustments, adjustment, adjustment);
NAME_ARGS(hadjustment,vadjustment);

COMPLEX_FUNCTION(set_app_paintable, int);
NAME_ARGS(paintablep);


FUNCTION(set_flags, "function(int:object)");
RETURNS(GTK.Widget);
{
  GTK_WIDGET_SET_FLAGS( GTK_WIDGET( THIS->obj ), sp[-1].u.integer );
  RETURN_THIS();
}

FUNCTION(unset_flags, "function(int:object)");
RETURNS(GTK.Widget);
{
  GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET( THIS->obj ), sp[-1].u.integer );
  RETURN_THIS();
}

FUNCTION(has_set_flags, "function(int:object)");
RETURNS(GTK.Widget);
{
  pop_n_elems(args);
  push_int( GTK_WIDGET_FLAGS(GTK_WIDGET(THIS->obj)) | sp[-1].u.integer );
}
