diff --git a/.gitattributes b/.gitattributes
index 1ced214a7ade3a1e188190f284488e61f400df86..6a619d6a87dcae06f13ac5492f6e828fb7a359f1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -4,6 +4,7 @@
 *.eps binary
 *.gif binary
 *.gz binary
+*.pbm binary
 *.png binary
 *.pnm binary
 *.rs binary
@@ -455,6 +456,13 @@ testfont binary
 /src/pike_types.h foreign_ident
 /src/port.c foreign_ident
 /src/port.h foreign_ident
+/src/post_modules/GL/Makefile.in foreign_ident
+/src/post_modules/GL/acconfig.h foreign_ident
+/src/post_modules/GL/auto.c.in foreign_ident
+/src/post_modules/GL/configure.in foreign_ident
+/src/post_modules/GL/top.c foreign_ident
+/src/post_modules/GTK/aclocal.m4 foreign_ident
+/src/post_modules/GTK/dummy.c foreign_ident
 /src/post_modules/Makefile.in foreign_ident
 /src/post_modules/configure.in foreign_ident
 /src/preprocessor.h foreign_ident
diff --git a/lib/modules/GDK.pmod b/lib/modules/GDK.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..111eaaa6eaef9d9618c58389efab0014f9940dcc
--- /dev/null
+++ b/lib/modules/GDK.pmod
@@ -0,0 +1,48 @@
+inherit "GTK.so";
+#define INDEX(x) predef::`->(this_object(),(x))
+
+object Atom = class 
+{
+  mapping atoms = ([]);
+
+  class fake_atom
+  {
+    object ra;
+    string n;
+    object get_atom()
+    {
+      if(ra) return ra;
+      return ra = Gdk_Atom( n, 0 );
+    }
+    string get_name()
+    {
+      return get_atom()->get_name();
+    }
+    void create(string q)
+    {
+      n = q;
+    }
+  }
+
+  object `[](string what)
+  {
+    if(atoms[what])
+      return atoms[what];
+    return atoms[what] = fake_atom( what );
+  }
+}();
+
+mixed `[](string what)
+{
+  if(what == "_module_value") return ([])[0];
+
+  if(what == "Atom") return Atom;
+
+  if(!zero_type(INDEX("Gdk"+what)))
+    return INDEX("Gdk"+what);
+  if(!zero_type(INDEX("GDK_"+what)))
+    return INDEX("GDK_"+what);
+  if(!zero_type(INDEX("GDK_"+upper_case(GTK.unsillycaps(what)))))
+    return INDEX("GDK_"+upper_case(GTK.unsillycaps(what)));
+  return  GDKSupport[what];
+}
diff --git a/lib/modules/GDKSupport.pmod/README b/lib/modules/GDKSupport.pmod/README
new file mode 100644
index 0000000000000000000000000000000000000000..bd61ddd25995616ae791e092e437857e4a5c7e9e
--- /dev/null
+++ b/lib/modules/GDKSupport.pmod/README
@@ -0,0 +1 @@
+Not Yet Used
diff --git a/lib/modules/GTKSupport.pmod/Alert.pike b/lib/modules/GTKSupport.pmod/Alert.pike
new file mode 100644
index 0000000000000000000000000000000000000000..cac1bc8d96dac2e6c12dcaba57d30eabe4ce9f8e
--- /dev/null
+++ b/lib/modules/GTKSupport.pmod/Alert.pike
@@ -0,0 +1,28 @@
+inherit GTK.Dialog;
+
+void begone(object w2)
+{
+  destruct( this_object() );
+} 
+
+object ok_button;
+
+GTK.Button ok()
+{
+  return ok_button;
+}
+
+void create(string text, string|void title)
+{
+  ::create();
+  object l = GTK.Label( text );
+  set_title( title||"Alert" );
+  l->set_justify( GTK.JUSTIFY_LEFT );
+  l->set_alignment(0.0, 0.5);
+  l->set_padding( 20, 20 );
+  vbox()->add( l->show() );
+  ok_button = GTK.Button("OK");
+  ok_button->signal_connect( "clicked", begone );
+  action_area()->add( ok_button->show() );
+  show();
+}
diff --git a/lib/modules/GTKSupport.pmod/MenuFactory.pmod b/lib/modules/GTKSupport.pmod/MenuFactory.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..cea49d78066ee96b46d82c3855b3bcb22254375c
--- /dev/null
+++ b/lib/modules/GTKSupport.pmod/MenuFactory.pmod
@@ -0,0 +1,220 @@
+#define FLAG_SHIFT   1
+#define FLAG_CTRL    4
+#define FLAG_ALT     8
+#define FLAG_ALTGR  16
+#define FLAG_META   64
+#define FLAG_HYPER 128
+#define FLAG_SUPER 256
+
+array parse_shortcut(string what)
+{
+  int flags;
+  int key;
+  
+  if(!what)
+    return ({0,0 });
+
+  string a, b;
+  if(sscanf(what, "%s-%s", a, b) != 2)
+  {
+    a="";
+    b=what;
+  }
+
+  foreach(a/"", string s)
+    switch(lower_case(s))
+    {
+     case "s": flags |= FLAG_SHIFT; break;
+     case "c": flags |= FLAG_CTRL; break;
+     case "1":
+     case "a": flags |= FLAG_ALT; break;
+     case "2":
+     case "g": flags |= FLAG_ALTGR; break; /* not visible.. */
+     case "3":
+     case "m": flags |= FLAG_META; break;  /* not visible.. */
+     case "4":
+     case "h": flags |= FLAG_HYPER; break; /* not visible.. */
+     case "5":
+     case "u": flags |= FLAG_SUPER; break; /* not visible.. */
+    }
+  return ({ flags, (b+"-")[0] });
+}
+
+string shortcut_to_string( int key, int mod )
+{
+  if(!key) return 0;
+  string m="";
+  if(mod & FLAG_SHIFT) m += "S";
+  if(mod & FLAG_CTRL) m += "C";
+  if(mod & FLAG_ALT) m += "A";
+  if(mod & FLAG_ALTGR) m += "G";
+  if(mod & FLAG_META) m += "M";
+  if(mod & FLAG_HYPER) m += "H";
+  if(mod & FLAG_SUPER) m += "U";
+  if(strlen(m)) m+= "-";
+  return sprintf("%s%c",m, key);
+}
+
+class MenuDef
+{
+  string menu_path;
+  int shortcut;
+  int flags, modifiers;
+  mixed arg;
+  function callback;
+
+  void assign_shortcut(string sc)
+  {
+    [modifiers,shortcut] = parse_shortcut(sc);
+  }
+
+  void selected(mixed q, object widget, mixed ... args)
+  {
+    if(callback) 
+    {
+      if(arrayp(arg))
+	callback( @arg, widget, @args );
+      else
+	callback( arg, widget, @args );
+    }
+  }
+
+  void create(string path, function|void cb, 
+	      mixed|void cbarg,
+	      string|void binding,
+	      int|void right)
+  {
+    menu_path = path;
+    flags = right;
+    callback = cb;
+    arg = cbarg;
+    assign_shortcut( binding );
+  }
+
+  function mbc;
+  array(object(MenuDef)) siblings;
+  mapping modifier_table;
+  void slice_n_dice()
+  {
+    if(!mbc) return;
+    if(!modifier_table)
+    {
+      modifier_table = ([]);
+      foreach(siblings, MenuDef o)
+      {
+	o->modifier_table = modifier_table;
+	if(o->shortcut)
+	  modifier_table[o->menu_path] = shortcut_to_string( o->shortcut,
+							     o->modifiers );
+      }
+    } else	      
+      modifier_table[menu_path]= shortcut_to_string( shortcut, modifiers );
+    mbc( modifier_table );
+  }
+
+  void install_accelerator(int i, object w, int flags, 
+                           mixed g, int k, int mods)
+  {
+    shortcut = k;
+    modifiers = mods;
+    remove_call_out(slice_n_dice);
+    call_out(slice_n_dice, 0.1);
+  }
+
+  void remove_accelerator(int i, object w)
+  {
+    modifiers=shortcut=0;
+    remove_call_out(slice_n_dice);
+    call_out(slice_n_dice, 0.1);
+  }
+}
+
+
+function mbar_mc;
+void set_menubar_modify_callback( function to )
+{
+  mbar_mc = to;
+}
+
+mapping menubar_objects = ([]);
+mapping get_menubar_mapping(  )
+{
+  return copy_value(menubar_objects);
+}
+
+mapping(string:GTK.Menu) submenues;
+mapping get_submenu_mapping(  )
+{
+  return copy_value(submenues);
+}
+
+array(object) MenuFactory( MenuDef ... definition )
+{
+  GTK.Menu_bar bar = GTK.Menu_bar();
+  GTK.AccelGroup table= GTK.AccelGroup();
+  menubar_objects = ([]);
+  submenues = (["":bar]);
+  mapping(string:GTK.RadioMenuItem) radiogroups = ([]);
+  foreach(definition, object d)
+  {
+    string path="";
+    object parent = bar;
+    array p = d->menu_path/"/";
+    foreach(p[..sizeof(p)-2], string segment)
+    {
+      path += segment+"/";
+      if(!submenues[path])
+      {
+	GTK.Menu_item i = GTK.Menu_item( segment );
+	submenues[path] = GTK.Menu();
+	submenues[path]->set_accel_group( table );
+//         d->menu_obj = submenues[path];
+	parent->append( i );
+	i->set_submenu( submenues[path] );
+	i->show();
+	menubar_objects[ path ] = i;
+      }
+      parent = submenues[path];
+    }
+    GTK.Item i;
+    string q,g;
+    sscanf(p[-1], "<%s>%s", q, p[-1]);
+    if(q) sscanf(q, "%s:%s", q, g);
+    switch( q )
+    {
+     default:
+       i = GTK.MenuItem( p[-1] );
+       break;
+     case "check":
+       i = GTK.CheckMenuItem( p[-1] );
+       break;
+     case "separator":
+       i = GTK.MenuItem();
+       i->set_state( GTK.STATE_INSENSITIVE );
+       break;
+     case "tearoff":
+       i = GTK.TearoffMenuItem();
+       break;
+    case "radio":
+      if (!radiogroups[path+":"+g]) {
+	i = GTK.RadioMenuItem( p[-1] );
+	radiogroups[path+":"+g] = i;
+      } else {
+	i = GTK.RadioMenuItem( p[-1], radiogroups[path+":"+g] );
+      }
+      break;
+    }
+    menubar_objects[ d->menu_path ] = i;
+    i->show();
+    parent->add( i );
+    if(d->shortcut)
+      i->add_accelerator( "activate", table, d->shortcut, d->modifiers,
+                          GTK.AccelVisible);
+    i->signal_connect( "activate", d->selected, 0 );
+    i->signal_connect("add_accelerator", d->install_accelerator,  0);
+    i->signal_connect("remove_accelerator",  d->remove_accelerator,   0);
+    d->mbc = mbar_mc;
+    d->siblings = definition;
+  }
+  return ({bar,table});
+}
diff --git a/lib/modules/GTKSupport.pmod/SClist.pike b/lib/modules/GTKSupport.pmod/SClist.pike
new file mode 100644
index 0000000000000000000000000000000000000000..07289349d5b063fdb63db62a839d008c62809303
--- /dev/null
+++ b/lib/modules/GTKSupport.pmod/SClist.pike
@@ -0,0 +1,24 @@
+inherit GTK.ScrolledWindow;
+
+object cl;
+void create( mixed ... args )
+{
+  ::create( GTK.Adjustment(), GTK.Adjustment() );
+  cl = GTK.Clist( @args );
+  add( cl->show() );
+}
+
+
+mixed `[](string what ) 
+{
+  switch(what)
+  {
+    case "create":     return create;
+    case "show":       return show;
+    case "set_usize":  return set_usize;
+    case "set_policy": return set_policy;
+  }
+  return cl[what]; 
+}
+
+mixed `->(string what ) { return `[]( what ); }
diff --git a/lib/modules/GTKSupport.pmod/Util.pmod b/lib/modules/GTKSupport.pmod/Util.pmod
new file mode 100644
index 0000000000000000000000000000000000000000..c746759f227c57a9b00399d02a965c2efb9a73a7
--- /dev/null
+++ b/lib/modules/GTKSupport.pmod/Util.pmod
@@ -0,0 +1,421 @@
+// This function will be easier to write in newer pikes, where there
+// will be a Image.ANY.decode function, but this will do for now. It
+// decoded an image from a string and returns a mapping with the
+// image, and optinally the alpha channel.
+// 
+// Currently supports most commonly used image formats, but only PNG
+// and GIF supports alpha channels
+//
+
+array(int) invert_color(array color )
+{
+  return ({ 255-color[0], 255-color[1], 255-color[2] });
+}
+
+
+mapping low_decode_image(string data, mixed tocolor)
+{
+  Image.image i, a;
+  string format;
+  mapping opts;
+  if(!data)
+    return 0; 
+
+  if( mappingp( tocolor ) )
+  {
+    opts = tocolor;
+    tocolor = 0;
+  }
+  
+  // Use the low-level decode function to get the alpha channel.
+  catch
+  {
+    array chunks = Image.GIF._decode( data );
+
+    // If there is more than one render chunk, the image is probably
+    // an animation. Handling animations is left as an exercise for
+    // the reader. :-)
+    foreach(chunks, mixed chunk)
+      if(arrayp(chunk) && chunk[0] == Image.GIF.RENDER )
+        [i,a] = chunk[3..4];
+    format = "GIF";
+  };
+
+  if(!i) catch
+  {
+    i = Image.GIF.decode( data );
+    format = "GIF";
+  };
+
+  // The JPEG format is only available if JPEG library was installed
+  // when pike was compiled, thus we have to conditionally compile
+  // this part of the code.
+#if constant(Image.JPEG) && constant(Image.JPEG.decode)
+  if(!i) catch
+  {
+    i = Image.JPEG.decode( data );
+    format = "JPEG";
+  };
+
+#endif
+
+#if constant(Image.XCF) && constant(Image.XCF._decode)
+  if(!i) catch
+  {
+    if(!opts) opts = ([]);
+    if( tocolor )
+    {
+      opts->background = (array)tocolor;
+      tocolor = 0;
+    }
+    mixed q = Image.XCF._decode( data, opts );
+    format = "XCF Gimp file";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.PSD) && constant(Image.PSD._decode)
+  if(!i) catch
+  {
+    mixed q = Image.PSD._decode( data, ([
+      "background":tocolor,
+      ]));
+    tocolor=0;
+    format = "PSD Photoshop file";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.PNG) && constant(Image.PNG._decode)
+  if(!i) catch
+  {
+    mixed q = Image.PNG._decode( data );
+    format = "PNG";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.BMP) && constant(Image.BMP._decode)
+  if(!i) catch
+  {
+    mixed q = Image.BMP._decode( data );
+    format = "Windows bitmap file";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.TGA) && constant(Image.TGA._decode)
+  if(!i) catch
+  {
+    mixed q = Image.TGA._decode( data );
+    format = "Targa";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.PCX) && constant(Image.PCX._decode)
+  if(!i) catch
+  {
+    mixed q = Image.PCX._decode( data );
+    format = "PCX";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.XBM) && constant(Image.XBM._decode)
+  if(!i) catch
+  {
+    mixed q = Image.XBM._decode( data, (["bg":tocolor||({255,255,255}),
+                                    "fg":invert_color(tocolor||({255,255,255})) ]));
+    format = "XBM";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.XPM) && constant(Image.XPM._decode)
+  if(!i) catch
+  {
+    mixed q = Image.XPM._decode( data );
+    format = "XPM";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.TIFF) && constant(Image.TIFF._decode)
+  if(!i) catch
+  {
+    mixed q = Image.TIFF._decode( data );
+    format = "TIFF";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.ILBM) && constant(Image.ILBM._decode)
+  if(!i) catch
+  {
+    mixed q = Image.ILBM._decode( data );
+    format = "ILBM";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.RAS) && constant(Image.RAS.decode)
+  if(!i) catch
+  {
+    i = Image.RAS.decode( data );
+    format = "Sun Raster";
+  };
+#endif
+
+#if constant(Image.PS) && constant(Image.PS._decode)
+  if(!i) catch
+  {
+    mixed q = Image.PS._decode( data );
+    format = "Postscript";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.XWD) && constant(Image.XWD.decode)
+  if(!i) catch
+  {
+    i = Image.XWD.decode( data );
+    format = "XWD";
+  };
+#endif
+
+#if constant(Image.AVS) && constant(Image.AVS._decode)
+  if(!i) catch
+  {
+    mixed q = Image.AVS._decode( data );
+    format = "AVS X";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+  if(!i)
+    catch{
+      i = Image.PNM.decode( data );
+      format = "PNM";
+    };
+
+
+/* Image formats without headers */
+#if constant(Image.HRZ) && constant(Image.HRZ._decode)
+  if(!i) catch
+  {
+    mixed q = Image.HRZ._decode( data );
+    format = "HRZ";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+#if constant(Image.WBF) && constant(Image.WBF._decode)
+  if(!i) catch
+  {
+    mixed q = Image.WBF._decode( data );
+    format = "WBF";
+    i = q->image;
+    a = q->alpha;
+  };
+#endif
+
+  if(!i) // No image could be decoded at all. 
+    return 0;
+
+  if( tocolor && i && a )
+  {
+    object o = Image.image( i->xsize(), i->ysize(), @tocolor );
+    o->paste_mask( i,a );
+    i = o;
+  }
+
+  return ([
+    "format":format,
+    "alpha":a,
+    "img":i,
+  ]);
+}
+
+
+string read_file(string file)
+{
+  string ext="";
+  sscanf(reverse(file),"%s.%s",ext,string rest);
+  string dcc;
+
+  switch(lower_case(reverse(ext)))
+  {
+   case "gz":
+   case "z":
+     dcc="gzip";
+     break;
+   case "bz":
+   case "bz2":
+     dcc = "bzip2";
+     break;
+  }
+
+  if( dcc )
+  {
+    object f = Stdio.File();
+    object p=f->pipe(Stdio.PROP_IPC);
+    Process.create_process(({dcc,"-c","-d",file}),(["stdout":p]));
+    destruct( p );
+    return f->read();
+  }
+  return Stdio.read_file( file );
+}
+
+// This function loads and decodes and image from disk.
+// Returns Image.image objects
+mapping low_load_image( string filename, mapping|array|void bgcol )
+{
+  string data;
+  catch(data = read_file(filename));
+  return low_decode_image(data,bgcol);
+}
+
+// returns GDK image objects.
+mapping load_image( string filename, array|void bgcol )
+{
+  if(mapping a = low_load_image( filename, bgcol ) )
+  return ([
+    "format":a->format,
+    "alpha": a->alpha && GDK.Bitmap( a->alpha ),
+    "img":  GDK.Pixmap( a->img ),
+  ]);
+}
+
+// returns GDK image objects.
+mapping decode_image( string data, mapping|array|void tocolor )
+{
+  if(mapping a = low_decode_image( data,tocolor ) )
+  return ([
+    "format":a->format,
+    "alpha": a->alpha && GDK.Bitmap( a->alpha ),
+    "img":   GDK.Pixmap( a->img ),
+  ]);
+}
+
+string low_encode_image( mapping img, string fmt )
+{
+  if(img->alpha) return 0;
+  catch {
+    return Image[fmt||"PNG"]->encode( img->img );
+  };
+  return 0;
+}
+
+string encode_image( mapping img, string fmt )
+{
+}
+
+
+
+
+// Some shortcut handling stuff.
+
+mapping parse_shortcut_file( string f )
+{
+  mapping ss = ([]);
+  Stdio.File o = Stdio.File();
+  if(o->open(f, "r"))
+  {
+    string p,k;
+    foreach(o->read()/"\n", string l)
+      if(sscanf(l, "\"%s\" \"%s\"", p, k) == 2)
+	ss[p] = k;
+  }
+  return ss;
+}
+
+void save_shortcut_file( string f, mapping ss )
+{
+  Stdio.File o = Stdio.File();
+  if(o->open(f, "wct"))
+  {
+    foreach(sort(indices(ss)), string s)
+      o->write( "\""+s+"\" \""+ss[s]+"\"\n" );
+  }
+}
+
+
+class signal_handling
+{
+  class Fun
+  {
+    mixed arg;
+    function tocall;
+
+    void `()(mixed ... args)
+    {
+      array err;
+      if(!tocall)
+        destruct();
+      else
+        if(err=catch(tocall(arg,@args)))
+        {
+          if(err == 1)
+          {
+            destruct();
+            return;
+          }
+          werror("signal error: %s\n", describe_backtrace( err ) );
+        }
+    }
+  
+    void create(function f, mixed a)
+    {
+      tocall = f;
+      arg = a;
+    }
+  }
+
+  mapping signals = ([]);
+  mapping r_signals = ([]);
+
+  mixed signal_connect( string signal, function tocall, mixed arg )
+  {
+    object ret;
+    if(signals[signal])
+      signals[signal]+=({ (ret=Fun( tocall, arg)) });
+    else
+      signals[signal]=({ (ret=Fun( tocall, arg)) });
+    r_signals[ret] = signal;
+    return ret;
+  }
+
+  void signal_disconnect( Fun what )
+  {
+    if(r_signals[what])
+    {
+      signals[r_signals[what]] -= ({ what });
+      m_delete( r_signals, what );
+      destruct(what);
+    }
+  }
+
+  void signal_broadcast( string signal, mixed ... args)
+  {
+    if(signals[signal]) 
+    {
+      signals[signal]-=({ 0 });
+      signals[signal]( this_object(), @args );
+      signals[signal]-=({ 0 });
+    }
+  }
+}
diff --git a/lib/modules/GTKSupport.pmod/pCtree.pike b/lib/modules/GTKSupport.pmod/pCtree.pike
new file mode 100644
index 0000000000000000000000000000000000000000..febe8fd2cb2239cebb60b276a616200b7b9a5951
--- /dev/null
+++ b/lib/modules/GTKSupport.pmod/pCtree.pike
@@ -0,0 +1,364 @@
+inherit GTK.Ctree:ctree;
+
+class Node
+{
+   private static object this=this_object();
+   private static program Prog=object_program(this_object());
+
+   private static GTK.CTreeNode node;
+
+   void create(object _node)
+   {
+      node=_node;
+   }
+
+   object(GTK.CTreeNode) get_node()
+   {
+      return node;
+   }
+
+   Node collapse()
+   {
+      ctree::collapse(node);
+      return this;
+   }
+   Node collapse_recursive()
+   {
+      ctree::collapse_recursive(node);
+      return this;
+   }
+   Node collapse_to_depth(int depth)
+   {
+      ctree::collapse_to_depth(node,depth);
+      return this;
+   }
+   Node expand()
+   {
+      ctree::expand(node);
+      return this;
+   }
+   Node expand_recursive()
+   {
+      ctree::expand_recursive(node);
+      return this;
+   }
+   Node expand_to_depth(int depth )
+   {
+      ctree::expand_to_depth(node,depth);
+      return this;
+   }
+
+   Node insert_sibling(array(string)|void columns, 
+		       void|int is_leaf,void|int expanded)
+   {
+      return Prog (ctree::insert_node(0,node,columns,is_leaf,expanded));
+   }
+
+   Node insert_child(array(string)|void columns, 
+		     void|int is_leaf,void|int expanded)
+   {
+      return Prog(ctree::insert_node(node,0,columns,is_leaf,expanded));
+   }
+
+   int is_ancestor(Node what)
+   {
+      return !!ctree::is_ancestor(node,what);
+   }
+
+   int is_viewable()
+   {
+      return !!ctree::is_viewable(node);
+   }
+
+   int is_visible()
+   {
+      return !!ctree::node_is_visible(node);
+   }
+   
+   Node last()
+   {
+      return Prog(ctree::last(node));
+   }
+
+   Node move_new_parent(Node parent)
+   {
+      ctree::move(node,parent,0);
+      return this;
+   }
+
+   Node move_new_sibling(Node sibling)
+   {
+      ctree::move(node,0,sibling);
+      return this;
+   }
+
+   GTK.style get_cell_style(int cell)
+   {
+      return ctree::node_get_cell_style(node,cell);
+   }
+
+   GTK.style get_style()
+   {
+      return ctree::node_get_row_style(node);
+   }
+
+   Node set_style(GTK.style style)
+   {
+      ctree::node_set_row_style(node,style);
+      return node;
+   }
+
+   int get_cell_type(int cell)
+   {
+      return !!ctree::node_get_cell_type(node,cell);
+   }
+
+   Node set_background(GDK.Color color)
+   {
+      ctree::node_set_background(node,color);
+      return this;
+   }
+
+   Node set_foreground(GDK.Color color)
+   {
+      ctree::node_set_foreground(node, color);
+      return this;
+   }
+
+   Node set_cell_style(int column,GTK.Style style)
+   {
+      ctree::node_set_cell_style(node, column, style);
+      return this;
+   }
+
+   int get_selectable()
+   {
+      return !!ctree::node_get_selectable(node);
+   }
+
+   Node set_selectable(int yes)
+   {
+      ctree::node_set_selectable(node,yes);
+      return this;
+   }
+
+   Node moveto(int column,void|float row_align,float|void col_align)
+   {
+      ctree::node_moveto(node,column,row_align||0.0,col_align||0.0);
+      return this;
+   }
+
+   string get_text(int column)
+   {
+      return ctree::node_get_text(node,column);
+   }
+
+   Node set_text(int column,string text)
+   {
+      ctree::node_set_text(node,column,text);
+      return this;
+   }
+
+   array(string) get_texts()
+   {
+      return Array.map(indices(allocate(ctree::get_columns())),get_text);
+   }
+
+   Node set_texts(array(string) what)
+   {
+      foreach (indices(what),int i) set_text(i,what[i]);
+      return this;
+   }
+
+   mapping get_pixmap( int column )
+   {
+      return node_get_pixmap(node,column);
+   }
+
+   mapping get_pixtext( int column )
+   {
+      return node_get_pixtext(node,column);
+   }
+
+   Node set_pixmap(int column, GDK.Pixmap pixmap,void|object(GDK.Bitmap) mask )
+   {
+      ctree::node_set_pixmap(node,column,pixmap,mask);
+      return this;
+   }
+
+   Node set_pixtext( int column, string text, int spacing, 
+		     GDK.Pixmap pixmap, object(GDK.Bitmap)|void mask)
+   {
+      ctree::node_set_pixtext(node,column,text,spacing,pixmap,mask);
+      return this;
+   }
+
+   Node set_data(object z)
+   {
+      ctree::node_set_row_data(node,z);
+      return this;
+   }
+
+   object get_data()
+   {
+      return ctree::node_get_row_data(node);
+   }
+   
+   Node set_info(string text, int spacing, 
+		 object(GDK.Pixmap)|void pixmap_closed, 
+		 object(GDK.Bitmap)|void mask_closed, 
+		 object(GDK.Pixmap)|void pixmap_opened, 
+		 object(GDK.Bitmap)|void mask_opened, 
+		 int is_leaf, int expanded )
+   {
+      ctree::set_node_info(node,text,spacing,pixmap_closed,
+			   mask_closed,pixmap_opened,mask_opened,
+			   is_leaf,expanded);
+      return this;
+   }
+
+   Node set_shift(int column,int vertical,int horizontal)
+   {
+      ctree::node_set_shift(node,column,vertical,horizontal);
+      return this;
+   }
+
+   void remove()
+   {
+      ctree::remove_node(node);
+      node=0;
+   }
+   
+   Node select()
+   {
+      ctree::select(node);
+      return this;
+   }
+
+   Node select_recursive()
+   {
+      ctree::select_recursive(node);
+      return this;
+   }
+
+   Node sort()
+   {
+      ctree::sort_node(node);
+      return this;
+   }
+
+   Node sort_recursive()
+   {
+      ctree::sort_recursive(node);
+      return this;
+   }
+
+   Node toggle_expansion()
+   {
+      ctree::toggle_expansion(node);
+      return this;
+   }
+
+   Node toggle_expansion_recursive()
+   {
+      ctree::toggle_expansion_recursive(node);
+      return this;
+   }
+
+   Node unselect()
+   {
+      ctree::unselect(node);
+      return this;
+   }
+
+   Node unselect_recursive()
+   {
+      ctree::unselect_recursive(node);
+      return this;
+   }
+
+   int find(Node what)
+   {
+      return (int)ctree::find(what->get_node(),node);
+   }
+
+   Node find_by_data(object data)
+   {
+      return Prog(ctree::find_by_row_data(data,node));
+   }
+
+   mixed `[](string z)
+   {
+      return ::`[](z) || (node && node[z]);
+   }
+
+   mixed `->(string z)
+   {
+      return `[](z);
+   }
+
+   array(string) _indices()
+   {
+      return indices(this)+(node?indices(node):({}));
+   }
+
+   array _values()
+   {
+      return Array.map(_indices(),`[]);
+   }
+
+   Node find_node_ptr()
+   {
+      return Prog(ctree::find_node_ptr(node));
+   }
+}
+
+object root=Node(0);
+
+Node node_nth(int i)
+{
+   return Node(ctree::node_nth(i));
+}
+
+static void collapse() {} /* (node); */
+static void collapse_recursive() {} /* (node); */
+static void collapse_to_depth() {} /* (node,depth); */
+static void expand() {} /* (node); */
+static void expand_recursive() {} /* (node); */
+static void expand_to_depth() {} /* (node,depth); */
+static void insert_node() {} /* (0,node,columns,is_leaf,expanded)); */
+static void is_ancestor() {} /* (node,what); */
+static void is_viewable() {} /* (node); */
+static void node_is_visable() {} /* (node); */
+static void last() {} /* (node)); */
+static void move() {} /* (node,parent,0); */
+static void node_get_cell_style() {} /* (node,cell); */
+static void node_get_row_style() {} /* (node); */
+static void node_set_row_style() {} /* (node,style); */
+static void node_get_cell_type() {} /* (node,cell); */
+static void set_background() {} /* (node,color); */
+static void node_set_foreground() {} /* (node, color); */
+static void node_set_cell_style() {} /* (node, style); */
+static void node_get_selectable() {} /* (node); */
+static void node_set_selectable() {} /* (node,yes); */
+static void node_moveto() {} /* (node,column,row_align||0.0,col_align||0.0); */
+static void node_get_text() {} /* (node,column); */
+static void node_set_text() {} /* (node,column,text); */
+static void columns() {} /* ())),get_text); */
+static void node_set_pixmap() {} /* (node,column,pixmap,mask); */
+static void node_set_pixtext() {} /* (node,column,text,spacing,pixmap,mask); */
+static void node_set_row_data() {} /* (node,z); */
+static void node_get_row_data() {} /* (node); */
+static void set_node_info() {} /* (node,text,spacing,pixmap_closed, */
+static void set_node_shift() {} /* (node,column,vertical,horizontal); */
+static void remove_node() {} /* (node); */
+static void select() {} /* (node); */
+static void select_recursive() {} /* (node); */
+static void sort_node() {} /* (node); */
+static void sort_recursive() {} /* (node); */
+static void toggle_expansion() {} /* (node); */
+static void toggle_expansion_recursive() {} /* (node); */
+static void unselect_expansion() {} /* (node); */
+static void unselect_expansion_recursive() {} /* (node); */
+static void find() {} /* (what->get_node(),node); */
+static void find_by_row_data() {} /* (what->get_node(),node)); */
diff --git a/lib/modules/GTKSupport.pmod/pDrawingArea.pike b/lib/modules/GTKSupport.pmod/pDrawingArea.pike
new file mode 100644
index 0000000000000000000000000000000000000000..56753bd7f0fe0d52cd5c2bd83e69c1502fc03e4a
--- /dev/null
+++ b/lib/modules/GTKSupport.pmod/pDrawingArea.pike
@@ -0,0 +1,152 @@
+inherit GTK.DrawingArea;
+static object backing_store, bgc;
+static int _xsize, _ysize, is_realized;
+
+#define WRAP(X) object X(mixed ... args) \
+   {                           \
+     if(xsize() != _xsize ||  \
+        ysize() != _ysize)   \
+       size(xsize(),ysize());                \
+     backing_store->X(@args);            \
+     refresh();                              \
+     return this_object();                   \
+   }
+
+object size(int x, int y)
+{
+  if(!is_realized) return this_object();
+  ::size(x,y);
+  if(!bgc) bgc = GDK.GC( background_pix||backing_store||this_object() );
+  object nb;
+  if((x>_xsize || y>_ysize) && x && y)
+    nb = GDK.Pixmap( Image.image(max(x,_xsize),max(y,_ysize)) );
+  if(nb && backing_store)
+  {
+    nb->draw_pixmap( bgc, backing_store, 0,0,0,0, _xsize, _ysize );
+    destruct(backing_store);
+  }
+  if(nb) backing_store = nb;
+  if(x>_xsize)
+  {
+    int ox=_xsize;
+    _xsize = x;
+    clear(ox, 0, x-ox, max(y,_ysize));
+  }
+  else if(x<_xsize)
+  {
+    _xsize = x;
+  }
+
+  if(y>_ysize)
+  {
+    int oy=_ysize;
+    _ysize = y;
+    clear(0, oy, max(x,_xsize), y-oy);
+  }
+  else if(y<_ysize)
+  {
+    _ysize = y;
+  }
+
+  refresh();
+  return this_object();
+}
+
+//object set_usize(int x, int y)
+//{
+//  call_out(size,0.01, x,y);
+//}
+
+static void rrefresh()
+{
+  if(!is_realized) return;
+  if(xsize() != _xsize || ysize() != _ysize) 
+    size(xsize(),ysize());
+  if(backing_store)
+  {
+    ::draw_pixmap( bgc, backing_store, 0, 0, 0, 0, _xsize, _ysize);
+    GTK.flush();
+  }
+}
+
+static void refresh()
+{
+  remove_call_out(rrefresh);
+  call_out(rrefresh,0.01);
+}
+
+void realized()
+{
+  call_out(lambda(){is_realized=1;},0);
+}
+
+void create()
+{
+  ::create();
+  signal_connect( "expose_event", refresh, 0 );
+  signal_connect( "realize", realized, 0 );
+//   ::set_usize( 100,100 );
+}
+
+GDK.Pixmap background_pix;
+GDK.Pixmap background_color;
+void set_background( GDK.Pixmap to )
+{
+  if(to->red)
+    background_color = to;
+  else
+    background_pix = to;
+  refresh();
+}
+
+object clear(int|void x, int|void y, int|void w, int|void h)
+{ 
+//   werror("%d,%d->%d,%d <%d,%d>\n", x, y, x+w, y+h, w, h);
+  if(xsize() != _xsize ||
+     ysize() != _ysize)
+    size(xsize(),ysize());
+  
+  if(!w && !h)
+  {
+    w = xsize();
+    h = ysize();
+  }
+  if(background_pix)
+  {
+    int sx = x+w;
+    int stx=x;
+    int sy = y+h;
+    for(; y<sy; x=stx,y+=background_pix->ysize()-y%background_pix->ysize())
+      for(; x<sx; x+=background_pix->xsize()-x%background_pix->xsize())
+        backing_store->draw_pixmap(bgc,
+                                   background_pix, 
+                                   (x%background_pix->xsize()),
+                                   (y%background_pix->ysize()),
+                                   x,y,
+                                   min(background_pix->xsize()-
+                                       (x%background_pix->xsize()),
+                                       sx-x),
+                                   min(background_pix->xsize()-
+                                       (y%background_pix->xsize()),
+                                       sy-y));
+  } else if(background_color) {
+    bgc->set_foreground( background_color );
+    backing_store->draw_rectangle( bgc, 1, x, y, x+w, y+h );
+  } else {
+//     if(!x && !y && h==_xsize && y == _ysize)
+//       backing_store->clear();
+//     else
+//       backing_store->clear(x,y,h,w);
+  }
+  refresh();
+  return this_object();
+}
+
+WRAP(draw_arc);
+WRAP(draw_bitmap);
+WRAP(draw_image);
+WRAP(draw_line);
+WRAP(draw_pixmap);
+WRAP(draw_point);
+WRAP(draw_rectangle);
+WRAP(draw_text);
diff --git a/src/post_modules/GL/.cvsignore b/src/post_modules/GL/.cvsignore
new file mode 100644
index 0000000000000000000000000000000000000000..ae2922eca1e0f8b1736b98ea944d7ec2143be3b4
--- /dev/null
+++ b/src/post_modules/GL/.cvsignore
@@ -0,0 +1,16 @@
+.pure
+Makefile
+config.h
+config.h.in
+config.log
+config.cache
+config.status
+configure
+dependencies
+linker_options
+modlist_headers
+modlist_segment
+module_testsuite
+stamp-h
+stamp-h.in
+auto.c
diff --git a/src/post_modules/GL/.gitignore b/src/post_modules/GL/.gitignore
new file mode 100644
index 0000000000000000000000000000000000000000..1d89051b2fe29636d48ba8d7518b581aa4b5234c
--- /dev/null
+++ b/src/post_modules/GL/.gitignore
@@ -0,0 +1,16 @@
+/.pure
+/Makefile
+/config.h
+/config.h.in
+/config.log
+/config.cache
+/config.status
+/configure
+/dependencies
+/linker_options
+/modlist_headers
+/modlist_segment
+/module_testsuite
+/stamp-h
+/stamp-h.in
+/auto.c
diff --git a/src/post_modules/GL/Makefile.in b/src/post_modules/GL/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..9f73212ce438a5b6eaa7799468a71b003028f423
--- /dev/null
+++ b/src/post_modules/GL/Makefile.in
@@ -0,0 +1,13 @@
+# $Id: Makefile.in,v 1.4 1999/11/07 01:43:31 per fake $
+SRCDIR=@srcdir@
+VPATH=@srcdir@:@srcdir@/../..:../..
+OBJS=top.o @AUTO_OBJS@
+MODULE_LDFLAGS=@LDFLAGS@ @LIBS@
+CONFIG_HEADERS=@CONFIG_HEADERS@
+
+@dynamic_module_makefile@
+
+$(SRCDIR)/auto.c : $(SRCDIR)/auto.c.in $(SRCDIR)/features.pike $(SRCDIR)/constants.pike $(SRCDIR)/gen.pike
+	$(RUNPIKE) $(SRCDIR)/gen.pike < $(SRCDIR)/auto.c.in > $(SRCDIR)/auto.c
+
+@dependencies@
diff --git a/src/post_modules/GL/acconfig.h b/src/post_modules/GL/acconfig.h
new file mode 100644
index 0000000000000000000000000000000000000000..71f05ce0e1114e7821cad7b0f8aa7f4afa791f16
--- /dev/null
+++ b/src/post_modules/GL/acconfig.h
@@ -0,0 +1,16 @@
+/* $Id: acconfig.h,v 1.3 1999/11/07 01:43:31 per fake $ */
+
+/* Define if you have libGL */
+#undef HAVE_LIBGL
+
+/* Define if you have libOpenGL */
+#undef HAVE_LIBOPENGL
+
+/* Define if you have libOpenGL32 */
+#undef HAVE_LIBOPENGL32
+
+/* Define if you have libMesaGL */
+#undef HAVE_LIBMESAGL
+
+/* Define if you have GL */
+#undef HAVE_GL
diff --git a/src/post_modules/GL/auto.c.in b/src/post_modules/GL/auto.c.in
new file mode 100644
index 0000000000000000000000000000000000000000..028febd0396cfe0b5ffcc92516c6b63777cbd181
--- /dev/null
+++ b/src/post_modules/GL/auto.c.in
@@ -0,0 +1,358 @@
+/*
+ * $Id: auto.c.in,v 1.13 1999/11/07 01:43:31 per fake $
+ *
+ */
+
+#include "global.h"
+
+#include "config.h"
+
+RCSID("$Id: auto.c.in,v 1.13 1999/11/07 01:43:31 per fake $");
+#include "stralloc.h"
+#include "pike_macros.h"
+#include "object.h"
+#include "program.h"
+#include "interpret.h"
+#include "builtin_functions.h"
+#include "error.h"
+#include "module_support.h"
+#include "operators.h"
+#include "mapping.h"
+
+#ifdef HAVE_WINDEF_H
+#include <windef.h>
+#endif /* HAVE_WINDEF_H */
+#ifdef HAVE_WINGDI_H
+#include <wingdi.h>
+#endif /* HAVE_WINGDI_H */
+#ifdef HAVE_GL_GL_H
+#include <GL/gl.h>
+#endif /* HAVE_GL_GL_H */
+
+#define ZT_INT    1
+#define ZT_FLOAT  2
+#define ZT_DOUBLE 4
+#define ZT_ARRAY  8
+
+struct zvalue4 {
+  union {
+    GLint i[4];
+    GLfloat f[4];
+    GLdouble d[4];
+  } v;
+  int ty;
+};
+
+union zvalue16 {
+  GLint i[16];
+  GLfloat f[16];
+  GLdouble d[16];
+};
+
+struct zimage {
+  GLsizei width, height;
+  GLenum format, type;
+  GLvoid *pixels;
+  int alloc;
+};
+
+static int check_234_args(char *func, INT32 args, int mn, int mx, int ty,
+			  int rty, struct zvalue4 *ret)
+{
+  struct svalue *s;
+  int i, tt, tr=0;
+
+  if(args==1 && sp[-1].type==T_ARRAY) {
+    struct array *a = sp[-1].u.array;
+    args = a->size;
+    if(args<mn || args>mx)
+      error("%s: expected array of size %d-%d.\n", func, mn, mx);
+    s = ITEM(a);
+  } else {
+    if(args<mn || args>mx)
+      error("%s: too %s arguments.\n", func, (args<mn? "few":"many"));
+    s = sp-args;
+  }
+  for(i=0; i<args; i++)
+    if(!((tt=1<<s[i].type)&ty)) {
+      char buf[32];
+      int n=0;
+      buf[0]='\0';
+      for(tt=0; ty; tt++)
+	if(ty&(1<<tt)) {
+	  ty&=~(1<<tt);
+	  if(n++)
+	    strcat(buf, " or ");
+	  strcat(buf, get_name_of_type(tt));
+	}
+      error("%s: got %s, expected %s.\n", func,
+	    get_name_of_type(s[i].type), buf);
+    } else
+      tr|=tt;
+  if(tr==(BIT_INT|BIT_FLOAT))
+    tt=((rty&ZT_DOUBLE)? ZT_DOUBLE:ZT_FLOAT);
+  else if(tr==BIT_FLOAT)
+    tt=((rty&ZT_FLOAT)? ZT_FLOAT:ZT_DOUBLE);
+  else if(tr!=BIT_INT)
+    error("Internal error in check_234_args for %s!\n", func);
+  else if(rty&ZT_INT)
+    tt=ZT_INT;
+  else 
+    tt=((rty&ZT_DOUBLE)? ZT_DOUBLE:ZT_FLOAT);
+  ret->ty=tt;
+  for(i=0; i<args; i++) 
+    switch(tt)
+    {
+    case ZT_INT:
+      ret->v.i[i]=s[i].u.integer;
+      break;
+    case ZT_FLOAT:
+      ret->v.f[i]=(s[i].type==T_INT?(float)s[i].u.integer:s[i].u.float_number);
+      break;      
+    case ZT_DOUBLE:
+      ret->v.d[i]=(s[i].type==T_INT?(double)s[i].u.integer:
+		   s[i].u.float_number);
+      break;      
+    }
+  return args;
+}
+
+static int img_inited=0;
+
+static void img_init()
+{
+  glPixelStorei(GL_PACK_SWAP_BYTES, 0);
+  glPixelStorei(GL_PACK_LSB_FIRST, 0);
+  glPixelStorei(GL_PACK_ROW_LENGTH, 0);
+  glPixelStorei(GL_PACK_SKIP_ROWS, 0);
+  glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
+  glPixelStorei(GL_PACK_ALIGNMENT, 1);
+  glPixelStorei(GL_UNPACK_SWAP_BYTES, 0);
+  glPixelStorei(GL_UNPACK_LSB_FIRST, 0);
+  glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
+  glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
+  glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
+  glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
+  img_inited=1;
+}
+
+static void check_img_arg(struct svalue *a, struct zimage *img,
+			  int arg, const char *func)
+{
+  struct {
+    void *img;
+    INT_TYPE w, h;
+  } *rgbstor = NULL, *lumstor = NULL, *astor = NULL;
+  unsigned char *pp;
+  struct { unsigned char r, g, b; } *p1, *p2;
+  INT32 cnt;
+
+  static struct program *image_program=NULL;
+
+  if(image_program == NULL) {
+    push_string(make_shared_string("Image")); push_int(0);
+    SAFE_APPLY_MASTER("resolv",2);
+    if (sp[-1].type==T_OBJECT) 
+    {
+      push_string(make_shared_string("image"));
+      f_index(2);
+      image_program=program_from_svalue(sp-1);
+      pop_stack();
+    }
+    if(image_program == NULL)
+      error("%s: Can't resolve Image.image!\n", func);
+  }
+
+  img->alloc = 0;
+  if(a->type == T_MAPPING) {
+    struct svalue *v;
+    if((v=simple_mapping_string_lookup(a->u.mapping, "rgb")))
+      if(v->type == T_OBJECT &&
+	 (rgbstor = (void *)get_storage(v->u.object, image_program)) != NULL &&
+	 rgbstor->img != NULL)
+	;
+      else
+	error("Bad argument %d to %s.\n", arg, func);
+    if((v=simple_mapping_string_lookup(a->u.mapping, "luminance")))
+      if(v->type == T_OBJECT &&
+	 (lumstor = (void *)get_storage(v->u.object, image_program)) != NULL &&
+	 lumstor->img != NULL)
+	;
+      else
+	error("Bad argument %d to %s.\n", arg, func);
+    if((v=simple_mapping_string_lookup(a->u.mapping, "alpha")))
+      if(v->type == T_OBJECT &&
+	 (astor = (void *)get_storage(v->u.object, image_program)) != NULL &&
+	 astor->img != NULL)
+	;
+      else
+	error("Bad argument %d to %s.\n", arg, func);    
+  } else if(a->type == T_OBJECT &&
+	    (rgbstor = (void *)get_storage(a->u.object, image_program)) !=
+	    NULL && rgbstor->img != NULL)
+    ;
+  else
+    error("Bad argument %d to %s.\n", arg, func);
+
+  if(rgbstor==NULL && lumstor==NULL && astor==NULL)
+    error("Too few images specified.\n");
+
+  if(rgbstor!=NULL && lumstor!=NULL)
+    error("Can't have both rgb and luminance data.\n");
+
+  if((rgbstor != NULL && astor != NULL &&
+      (rgbstor->w != astor->w || rgbstor->h != astor->h)) ||
+     (lumstor != NULL && astor != NULL &&
+      (lumstor->w != astor->w || lumstor->h != astor->h)))
+    error("Alpha channel must have same size as image!\n");
+
+  if(lumstor==NULL && astor==NULL) {
+    /* RGB */
+    img->width = rgbstor->w;
+    img->height = rgbstor->h;
+    img->pixels = rgbstor->img;
+    img->format = GL_RGB;
+    img->type = GL_UNSIGNED_BYTE;
+  } else if(rgbstor != NULL) {
+    /* RGBA */
+    img->width = rgbstor->w;
+    img->height = rgbstor->h;
+    img->pixels = pp = xalloc(img->width*img->height*4);
+    img->format = GL_RGBA;
+    img->type = GL_UNSIGNED_BYTE;
+    cnt = img->width * img->height;
+    p1 = rgbstor->img;
+    p2 = astor->img;
+    while(cnt--) {
+      *pp++ = p1->r;
+      *pp++ = p1->g;
+      *pp++ = p1++->b;
+      *pp++ = p2++->r;
+    }
+  } else if(astor == NULL) {
+    /* Y */
+    img->width = lumstor->w;
+    img->height = lumstor->h;
+    img->pixels = pp = xalloc(img->width*img->height);
+    img->format = GL_LUMINANCE;
+    img->type = GL_UNSIGNED_BYTE;
+    cnt = img->width * img->height;
+    p1 = lumstor->img;
+    while(cnt--)
+      *pp++ = p1++->r;
+  } else if(lumstor == NULL) {
+    /* A */
+    img->width = astor->w;
+    img->height = astor->h;
+    img->pixels = pp = xalloc(img->width*img->height);
+    img->format = GL_ALPHA;
+    img->type = GL_UNSIGNED_BYTE;
+    cnt = img->width * img->height;
+    p1 = astor->img;
+    while(cnt--)
+      *pp++ = p1++->r;
+  } else {
+    /* YA */
+    img->width = lumstor->w;
+    img->height = lumstor->h;
+    img->pixels = pp = xalloc(img->width*img->height*2);
+    img->format = GL_LUMINANCE_ALPHA;
+    img->type = GL_UNSIGNED_BYTE;
+    cnt = img->width * img->height;
+    p1 = lumstor->img;
+    p2 = astor->img;
+    while(cnt--) {
+      *pp++ = p1++->r;
+      *pp++ = p2++->r;
+    }
+  }
+  if(!img_inited)
+    img_init();
+}
+
+static void release_img(struct zimage *img)
+{
+  if(img->alloc)
+    free(img->pixels);
+}
+
+static int check_1n_args(char *func, INT32 args, int ty, int rty,
+			 union zvalue16 *ret)
+{
+  int i, tt, tr=0, arr=0;
+  struct svalue *s;
+
+  if(args!=1)
+    error("%s: too %s arguments.\n", func, (args<1? "few":"many"));
+  
+  if(sp[-1].type==T_ARRAY) {
+    struct array *a = sp[-1].u.array;
+    args = a->size;
+    if(args>16)
+      error("%s: array too large.\n", func);
+    arr++;
+    s = ITEM(a);
+  } else
+    s = sp-args;
+
+  for(i=0; i<args; i++)
+    if(!((tt=1<<s[i].type)&ty)) {
+      char buf[32];
+      int n=0;
+      buf[0]='\0';
+      for(tt=0; ty; tt++)
+	if(ty&(1<<tt)) {
+	  ty&=~(1<<tt);
+	  if(n++)
+	    strcat(buf, " or ");
+	  strcat(buf, get_name_of_type(tt));
+	}
+      error("%s: got %s, expected %s.\n", func,
+	    get_name_of_type(s[i].type), buf);
+    } else
+      tr|=tt;
+  if(tr==(BIT_INT|BIT_FLOAT))
+    tt=((rty&ZT_DOUBLE)? ZT_DOUBLE:ZT_FLOAT);
+  else if(tr==BIT_FLOAT)
+    tt=((rty&ZT_FLOAT)? ZT_FLOAT:ZT_DOUBLE);
+  else if(tr!=BIT_INT)
+    error("Internal error in check_1n_args for %s!\n", func);
+  else if(rty&ZT_INT)
+    tt=ZT_INT;
+  else 
+    tt=((rty&ZT_DOUBLE)? ZT_DOUBLE:ZT_FLOAT);
+
+  for(i=0; i<args; i++) 
+    switch(tt)
+    {
+    case ZT_INT:
+      ret->i[i]=s[i].u.integer;
+      break;
+    case ZT_FLOAT:
+      ret->f[i]=(s[i].type==T_INT?(float)s[i].u.integer:s[i].u.float_number);
+      break;      
+    case ZT_DOUBLE:
+      ret->d[i]=(s[i].type==T_INT?(double)s[i].u.integer:s[i].u.float_number);
+      break;      
+    }  
+
+  return tt|(arr?ZT_ARRAY:0);
+}
+
+#define glClearColor3v(f) glClearColor((f)[0], (f)[1], (f)[2], 0.0)
+#define glClearColor4v(f) glClearColor((f)[0], (f)[1], (f)[2], (f)[3])
+#define glClearAccum3v(f) glClearAccum((f)[0], (f)[1], (f)[2], 0.0)
+#define glClearAccum4v(f) glClearAccum((f)[0], (f)[1], (f)[2], (f)[3])
+#define glEvalPoint1v(i) glEvalPoint1((i)[0]);
+#define glEvalPoint2v(i) glEvalPoint2((i)[0], (i)[1]);
+
+static void pre_init()
+{
+}
+
+static void post_init()
+{
+}
+
+@@
+
diff --git a/src/post_modules/GL/configure.in b/src/post_modules/GL/configure.in
new file mode 100755
index 0000000000000000000000000000000000000000..8c098ee6b5e322ca104d6e213c4e3eafe5f16a8a
--- /dev/null
+++ b/src/post_modules/GL/configure.in
@@ -0,0 +1,101 @@
+# $Id: configure.in,v 1.6 1999/11/07 01:43:31 per fake $
+AC_INIT(top.c)
+AC_CONFIG_HEADER(config.h)
+
+AC_MODULE_INIT()
+
+AC_ARG_WITH(GL,  [  --without-GL       no support for GL],[],[with_GL=yes])
+
+AUTO_OBJS=""
+
+if test x$with_GL = xno; then
+  :
+else
+
+AC_PATH_XTRA()
+
+AC_ARG_WITH(lib-GL,     [  --with-lib-GL           use '-lGL'])
+AC_ARG_WITH(lib-MesaGL, [  --with-lib-MesaGL       use '-lMesaGL'])
+
+AC_CHECK_HEADERS(windef.h wingdi.h GL/gl.h GL/glx.h)
+
+AC_CHECK_LIB(X11,XDrawPoint)
+AC_CHECK_LIB(Xext,XShmPutImage)
+
+AC_CHECK_LIB(GL, glOrtho, AC_DEFINE_UNQUOTED(HAVE_LIBGL),,[$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS])
+AC_CHECK_LIB(MesaGL, glOrtho, AC_DEFINE_UNQUOTED(HAVE_LIBMESAGL),,[$X_LIBS $X_PRE_LIBS -lXext -lX11 $X_EXTRA_LIBS])
+oldLIBS="$LIBS"
+AC_MSG_CHECKING(for glOrtho in -lOpenGL)
+AC_CACHE_VAL(pike_cv_lib_OpenGL, [
+  LIBS="$oldLIBS -lOpenGL"
+  AC_TRY_LINK([
+#ifdef HAVE_WINDEF_H
+#include <windef.h>
+#endif /* HAVE_WINDEF_H */
+#ifdef HAVE_WINGDI_H
+#include <wingdi.h>
+#endif /* HAVE_WINGDI_H */
+#ifdef HAVE_GL_GL_H
+#include <GL/gl.h>
+#endif /* HAVE_GL_GL_H */
+], [ glOrtho(0.0,0.0,0.0,0.0,0.0,0.0); ], [ pike_cv_lib_OpenGL=yes ], [ pike_cv_lib_OpenGL=no ])
+])
+if test x"$pike_cv_lib_OpenGL" = xyes; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE_UNQUOTED(HAVE_LIBOPENGL)
+else
+  AC_MSG_RESULT(no)
+fi
+AC_MSG_CHECKING(for glOrtho in -lOpenGL32)
+AC_CACHE_VAL(pike_cv_lib_OpenGL32, [
+  LIBS="$oldLIBS -lOpenGL32"
+  AC_TRY_LINK([
+#ifdef HAVE_WINDEF_H
+#include <windef.h>
+#endif /* HAVE_WINDEF_H */
+#ifdef HAVE_WINGDI_H
+#include <wingdi.h>
+#endif /* HAVE_WINGDI_H */
+#ifdef HAVE_GL_GL_H
+#include <GL/gl.h>
+#endif /* HAVE_GL_GL_H */
+], [ glOrtho(0.0,0.0,0.0,0.0,0.0,0.0); ], [ pike_cv_lib_OpenGL32=yes ], [ pike_cv_lib_OpenGL32=no ])
+])
+if test x"$pike_cv_lib_OpenGL32" = xyes; then
+  AC_MSG_RESULT(yes)
+  AC_DEFINE_UNQUOTED(HAVE_LIBOPENGL32)
+else
+  AC_MSG_RESULT(no)
+fi
+LIBS="$oldLIBS"
+
+if test x"$with_lib_GL" = "xyes" -a x"$ac_cv_lib_GL_glOrtho" = xyes; then
+  LIBS="-lGL $LIBS"
+  AC_DEFINE(HAVE_GL)
+elif test x"$with_lib_GL" = "xyes" -a x"$pike_cv_lib_OpenGL" = xyes; then
+  LIBS="-lOpenGL $LIBS"
+  AC_DEFINE(HAVE_GL)
+elif test x"$with_lib_GL" = "xyes" -a x"$pike_cv_lib_OpenGL32" = xyes; then
+  LIBS="-lOpenGL32 $LIBS"
+  AC_DEFINE(HAVE_GL)
+elif test x"$with_lib_MesaGL" = "xyes" -a x"$ac_cv_lib_MesaGL_glOrtho" = xyes; then
+  LIBS="-lMesaGL $LIBS"
+elif test x"$ac_cv_lib_GL_glOrtho" = xyes; then
+  LIBS="-lGL $LIBS"
+elif test x"$pike_cv_lib_OpenGL" = xyes; then
+  LIBS="-lOpenGL $LIBS"
+elif test x"$pike_cv_lib_OpenGL32" = xyes; then
+  LIBS="-lOpenGL32 $LIBS"
+elif test x"$ac_cv_lib_MesaGL_glOrtho" = xyes; then
+  LIBS="-lMesaGL $LIBS"
+else
+  AC_MSG_ERROR([You need GL or MesaGL libraries])
+fi
+
+AC_DEFINE(HAVE_GL)
+AUTO_OBJS="auto.o"
+
+fi
+
+AC_SUBST(AUTO_OBJS)
+AC_OUTPUT(Makefile,echo FOO >stamp-h )
diff --git a/src/post_modules/GL/constants.pike b/src/post_modules/GL/constants.pike
new file mode 100644
index 0000000000000000000000000000000000000000..94685304cad0abeeb818adabf4b827b928c7866c
--- /dev/null
+++ b/src/post_modules/GL/constants.pike
@@ -0,0 +1,653 @@
+mapping constants = ([
+ "GL_EXT_convolution":1,
+ "GL_VERSION_1_1":1,
+ "GL_ACCUM":0x0100,
+ "GL_LOAD":0x0101,
+ "GL_RETURN":0x0102,
+ "GL_MULT":0x0103,
+ "GL_ADD":0x0104,
+ "GL_NEVER":0x0200,
+ "GL_LESS":0x0201,
+ "GL_EQUAL":0x0202,
+ "GL_LEQUAL":0x0203,
+ "GL_GREATER":0x0204,
+ "GL_NOTEQUAL":0x0205,
+ "GL_GEQUAL":0x0206,
+ "GL_ALWAYS":0x0207,
+ "GL_CURRENT_BIT":0x00000001,
+ "GL_POINT_BIT":0x00000002,
+ "GL_LINE_BIT":0x00000004,
+ "GL_POLYGON_BIT":0x00000008,
+ "GL_POLYGON_STIPPLE_BIT":0x00000010,
+ "GL_PIXEL_MODE_BIT":0x00000020,
+ "GL_LIGHTING_BIT":0x00000040,
+ "GL_FOG_BIT":0x00000080,
+ "GL_DEPTH_BUFFER_BIT":0x00000100,
+ "GL_ACCUM_BUFFER_BIT":0x00000200,
+ "GL_STENCIL_BUFFER_BIT":0x00000400,
+ "GL_VIEWPORT_BIT":0x00000800,
+ "GL_TRANSFORM_BIT":0x00001000,
+ "GL_ENABLE_BIT":0x00002000,
+ "GL_COLOR_BUFFER_BIT":0x00004000,
+ "GL_HINT_BIT":0x00008000,
+ "GL_EVAL_BIT":0x00010000,
+ "GL_LIST_BIT":0x00020000,
+ "GL_TEXTURE_BIT":0x00040000,
+ "GL_SCISSOR_BIT":0x00080000,
+ "GL_ALL_ATTRIB_BITS":0x000fffff,
+ "GL_POINTS":0x0000,
+ "GL_LINES":0x0001,
+ "GL_LINE_LOOP":0x0002,
+ "GL_LINE_STRIP":0x0003,
+ "GL_TRIANGLES":0x0004,
+ "GL_TRIANGLE_STRIP":0x0005,
+ "GL_TRIANGLE_FAN":0x0006,
+ "GL_QUADS":0x0007,
+ "GL_QUAD_STRIP":0x0008,
+ "GL_POLYGON":0x0009,
+ "GL_ZERO":0,
+ "GL_ONE":1,
+ "GL_SRC_COLOR":0x0300,
+ "GL_ONE_MINUS_SRC_COLOR":0x0301,
+ "GL_SRC_ALPHA":0x0302,
+ "GL_ONE_MINUS_SRC_ALPHA":0x0303,
+ "GL_DST_ALPHA":0x0304,
+ "GL_ONE_MINUS_DST_ALPHA":0x0305,
+ "GL_DST_COLOR":0x0306,
+ "GL_ONE_MINUS_DST_COLOR":0x0307,
+ "GL_SRC_ALPHA_SATURATE":0x0308,
+ "GL_TRUE":1,
+ "GL_FALSE":0,
+ "GL_CLIP_PLANE0":0x3000,
+ "GL_CLIP_PLANE1":0x3001,
+ "GL_CLIP_PLANE2":0x3002,
+ "GL_CLIP_PLANE3":0x3003,
+ "GL_CLIP_PLANE4":0x3004,
+ "GL_CLIP_PLANE5":0x3005,
+ "GL_BYTE":0x1400,
+ "GL_UNSIGNED_BYTE":0x1401,
+ "GL_SHORT":0x1402,
+ "GL_UNSIGNED_SHORT":0x1403,
+ "GL_INT":0x1404,
+ "GL_UNSIGNED_INT":0x1405,
+ "GL_FLOAT":0x1406,
+ "GL_2_BYTES":0x1407,
+ "GL_3_BYTES":0x1408,
+ "GL_4_BYTES":0x1409,
+ "GL_DOUBLE":0x140A,
+ "GL_NONE":0,
+ "GL_FRONT_LEFT":0x0400,
+ "GL_FRONT_RIGHT":0x0401,
+ "GL_BACK_LEFT":0x0402,
+ "GL_BACK_RIGHT":0x0403,
+ "GL_FRONT":0x0404,
+ "GL_BACK":0x0405,
+ "GL_LEFT":0x0406,
+ "GL_RIGHT":0x0407,
+ "GL_FRONT_AND_BACK":0x0408,
+ "GL_AUX0":0x0409,
+ "GL_AUX1":0x040A,
+ "GL_AUX2":0x040B,
+ "GL_AUX3":0x040C,
+ "GL_NO_ERROR":0,
+ "GL_INVALID_ENUM":0x0500,
+ "GL_INVALID_VALUE":0x0501,
+ "GL_INVALID_OPERATION":0x0502,
+ "GL_STACK_OVERFLOW":0x0503,
+ "GL_STACK_UNDERFLOW":0x0504,
+ "GL_OUT_OF_MEMORY":0x0505,
+ "GL_2D":0x0600,
+ "GL_3D":0x0601,
+ "GL_3D_COLOR":0x0602,
+ "GL_3D_COLOR_TEXTURE":0x0603,
+ "GL_4D_COLOR_TEXTURE":0x0604,
+ "GL_PASS_THROUGH_TOKEN":0x0700,
+ "GL_POINT_TOKEN":0x0701,
+ "GL_LINE_TOKEN":0x0702,
+ "GL_POLYGON_TOKEN":0x0703,
+ "GL_BITMAP_TOKEN":0x0704,
+ "GL_DRAW_PIXEL_TOKEN":0x0705,
+ "GL_COPY_PIXEL_TOKEN":0x0706,
+ "GL_LINE_RESET_TOKEN":0x0707,
+ "GL_EXP":0x0800,
+ "GL_EXP2":0x0801,
+ "GL_CW":0x0900,
+ "GL_CCW":0x0901,
+ "GL_COEFF":0x0A00,
+ "GL_ORDER":0x0A01,
+ "GL_DOMAIN":0x0A02,
+ "GL_CURRENT_COLOR":0x0B00,
+ "GL_CURRENT_INDEX":0x0B01,
+ "GL_CURRENT_NORMAL":0x0B02,
+ "GL_CURRENT_TEXTURE_COORDS":0x0B03,
+ "GL_CURRENT_RASTER_COLOR":0x0B04,
+ "GL_CURRENT_RASTER_INDEX":0x0B05,
+ "GL_CURRENT_RASTER_TEXTURE_COORDS":0x0B06,
+ "GL_CURRENT_RASTER_POSITION":0x0B07,
+ "GL_CURRENT_RASTER_POSITION_VALID":0x0B08,
+ "GL_CURRENT_RASTER_DISTANCE":0x0B09,
+ "GL_POINT_SMOOTH":0x0B10,
+ "GL_POINT_SIZE":0x0B11,
+ "GL_POINT_SIZE_RANGE":0x0B12,
+ "GL_POINT_SIZE_GRANULARITY":0x0B13,
+ "GL_LINE_SMOOTH":0x0B20,
+ "GL_LINE_WIDTH":0x0B21,
+ "GL_LINE_WIDTH_RANGE":0x0B22,
+ "GL_LINE_WIDTH_GRANULARITY":0x0B23,
+ "GL_LINE_STIPPLE":0x0B24,
+ "GL_LINE_STIPPLE_PATTERN":0x0B25,
+ "GL_LINE_STIPPLE_REPEAT":0x0B26,
+ "GL_LIST_MODE":0x0B30,
+ "GL_MAX_LIST_NESTING":0x0B31,
+ "GL_LIST_BASE":0x0B32,
+ "GL_LIST_INDEX":0x0B33,
+ "GL_POLYGON_MODE":0x0B40,
+ "GL_POLYGON_SMOOTH":0x0B41,
+ "GL_POLYGON_STIPPLE":0x0B42,
+ "GL_EDGE_FLAG":0x0B43,
+ "GL_CULL_FACE":0x0B44,
+ "GL_CULL_FACE_MODE":0x0B45,
+ "GL_FRONT_FACE":0x0B46,
+ "GL_LIGHTING":0x0B50,
+ "GL_LIGHT_MODEL_LOCAL_VIEWER":0x0B51,
+ "GL_LIGHT_MODEL_TWO_SIDE":0x0B52,
+ "GL_LIGHT_MODEL_AMBIENT":0x0B53,
+ "GL_SHADE_MODEL":0x0B54,
+ "GL_COLOR_MATERIAL_FACE":0x0B55,
+ "GL_COLOR_MATERIAL_PARAMETER":0x0B56,
+ "GL_COLOR_MATERIAL":0x0B57,
+ "GL_FOG":0x0B60,
+ "GL_FOG_INDEX":0x0B61,
+ "GL_FOG_DENSITY":0x0B62,
+ "GL_FOG_START":0x0B63,
+ "GL_FOG_END":0x0B64,
+ "GL_FOG_MODE":0x0B65,
+ "GL_FOG_COLOR":0x0B66,
+ "GL_DEPTH_RANGE":0x0B70,
+ "GL_DEPTH_TEST":0x0B71,
+ "GL_DEPTH_WRITEMASK":0x0B72,
+ "GL_DEPTH_CLEAR_VALUE":0x0B73,
+ "GL_DEPTH_FUNC":0x0B74,
+ "GL_ACCUM_CLEAR_VALUE":0x0B80,
+ "GL_STENCIL_TEST":0x0B90,
+ "GL_STENCIL_CLEAR_VALUE":0x0B91,
+ "GL_STENCIL_FUNC":0x0B92,
+ "GL_STENCIL_VALUE_MASK":0x0B93,
+ "GL_STENCIL_FAIL":0x0B94,
+ "GL_STENCIL_PASS_DEPTH_FAIL":0x0B95,
+ "GL_STENCIL_PASS_DEPTH_PASS":0x0B96,
+ "GL_STENCIL_REF":0x0B97,
+ "GL_STENCIL_WRITEMASK":0x0B98,
+ "GL_MATRIX_MODE":0x0BA0,
+ "GL_NORMALIZE":0x0BA1,
+ "GL_VIEWPORT":0x0BA2,
+ "GL_MODELVIEW_STACK_DEPTH":0x0BA3,
+ "GL_PROJECTION_STACK_DEPTH":0x0BA4,
+ "GL_TEXTURE_STACK_DEPTH":0x0BA5,
+ "GL_MODELVIEW_MATRIX":0x0BA6,
+ "GL_PROJECTION_MATRIX":0x0BA7,
+ "GL_TEXTURE_MATRIX":0x0BA8,
+ "GL_ATTRIB_STACK_DEPTH":0x0BB0,
+ "GL_CLIENT_ATTRIB_STACK_DEPTH":0x0BB1,
+ "GL_ALPHA_TEST":0x0BC0,
+ "GL_ALPHA_TEST_FUNC":0x0BC1,
+ "GL_ALPHA_TEST_REF":0x0BC2,
+ "GL_DITHER":0x0BD0,
+ "GL_BLEND_DST":0x0BE0,
+ "GL_BLEND_SRC":0x0BE1,
+ "GL_BLEND":0x0BE2,
+ "GL_LOGIC_OP_MODE":0x0BF0,
+ "GL_INDEX_LOGIC_OP":0x0BF1,
+ "GL_COLOR_LOGIC_OP":0x0BF2,
+ "GL_AUX_BUFFERS":0x0C00,
+ "GL_DRAW_BUFFER":0x0C01,
+ "GL_READ_BUFFER":0x0C02,
+ "GL_SCISSOR_BOX":0x0C10,
+ "GL_SCISSOR_TEST":0x0C11,
+ "GL_INDEX_CLEAR_VALUE":0x0C20,
+ "GL_INDEX_WRITEMASK":0x0C21,
+ "GL_COLOR_CLEAR_VALUE":0x0C22,
+ "GL_COLOR_WRITEMASK":0x0C23,
+ "GL_INDEX_MODE":0x0C30,
+ "GL_RGBA_MODE":0x0C31,
+ "GL_DOUBLEBUFFER":0x0C32,
+ "GL_STEREO":0x0C33,
+ "GL_RENDER_MODE":0x0C40,
+ "GL_PERSPECTIVE_CORRECTION_HINT":0x0C50,
+ "GL_POINT_SMOOTH_HINT":0x0C51,
+ "GL_LINE_SMOOTH_HINT":0x0C52,
+ "GL_POLYGON_SMOOTH_HINT":0x0C53,
+ "GL_FOG_HINT":0x0C54,
+ "GL_TEXTURE_GEN_S":0x0C60,
+ "GL_TEXTURE_GEN_T":0x0C61,
+ "GL_TEXTURE_GEN_R":0x0C62,
+ "GL_TEXTURE_GEN_Q":0x0C63,
+ "GL_PIXEL_MAP_I_TO_I":0x0C70,
+ "GL_PIXEL_MAP_S_TO_S":0x0C71,
+ "GL_PIXEL_MAP_I_TO_R":0x0C72,
+ "GL_PIXEL_MAP_I_TO_G":0x0C73,
+ "GL_PIXEL_MAP_I_TO_B":0x0C74,
+ "GL_PIXEL_MAP_I_TO_A":0x0C75,
+ "GL_PIXEL_MAP_R_TO_R":0x0C76,
+ "GL_PIXEL_MAP_G_TO_G":0x0C77,
+ "GL_PIXEL_MAP_B_TO_B":0x0C78,
+ "GL_PIXEL_MAP_A_TO_A":0x0C79,
+ "GL_PIXEL_MAP_I_TO_I_SIZE":0x0CB0,
+ "GL_PIXEL_MAP_S_TO_S_SIZE":0x0CB1,
+ "GL_PIXEL_MAP_I_TO_R_SIZE":0x0CB2,
+ "GL_PIXEL_MAP_I_TO_G_SIZE":0x0CB3,
+ "GL_PIXEL_MAP_I_TO_B_SIZE":0x0CB4,
+ "GL_PIXEL_MAP_I_TO_A_SIZE":0x0CB5,
+ "GL_PIXEL_MAP_R_TO_R_SIZE":0x0CB6,
+ "GL_PIXEL_MAP_G_TO_G_SIZE":0x0CB7,
+ "GL_PIXEL_MAP_B_TO_B_SIZE":0x0CB8,
+ "GL_PIXEL_MAP_A_TO_A_SIZE":0x0CB9,
+ "GL_UNPACK_SWAP_BYTES":0x0CF0,
+ "GL_UNPACK_LSB_FIRST":0x0CF1,
+ "GL_UNPACK_ROW_LENGTH":0x0CF2,
+ "GL_UNPACK_SKIP_ROWS":0x0CF3,
+ "GL_UNPACK_SKIP_PIXELS":0x0CF4,
+ "GL_UNPACK_ALIGNMENT":0x0CF5,
+ "GL_PACK_SWAP_BYTES":0x0D00,
+ "GL_PACK_LSB_FIRST":0x0D01,
+ "GL_PACK_ROW_LENGTH":0x0D02,
+ "GL_PACK_SKIP_ROWS":0x0D03,
+ "GL_PACK_SKIP_PIXELS":0x0D04,
+ "GL_PACK_ALIGNMENT":0x0D05,
+ "GL_MAP_COLOR":0x0D10,
+ "GL_MAP_STENCIL":0x0D11,
+ "GL_INDEX_SHIFT":0x0D12,
+ "GL_INDEX_OFFSET":0x0D13,
+ "GL_RED_SCALE":0x0D14,
+ "GL_RED_BIAS":0x0D15,
+ "GL_ZOOM_X":0x0D16,
+ "GL_ZOOM_Y":0x0D17,
+ "GL_GREEN_SCALE":0x0D18,
+ "GL_GREEN_BIAS":0x0D19,
+ "GL_BLUE_SCALE":0x0D1A,
+ "GL_BLUE_BIAS":0x0D1B,
+ "GL_ALPHA_SCALE":0x0D1C,
+ "GL_ALPHA_BIAS":0x0D1D,
+ "GL_DEPTH_SCALE":0x0D1E,
+ "GL_DEPTH_BIAS":0x0D1F,
+ "GL_MAX_EVAL_ORDER":0x0D30,
+ "GL_MAX_LIGHTS":0x0D31,
+ "GL_MAX_CLIP_PLANES":0x0D32,
+ "GL_MAX_TEXTURE_SIZE":0x0D33,
+ "GL_MAX_PIXEL_MAP_TABLE":0x0D34,
+ "GL_MAX_ATTRIB_STACK_DEPTH":0x0D35,
+ "GL_MAX_MODELVIEW_STACK_DEPTH":0x0D36,
+ "GL_MAX_NAME_STACK_DEPTH":0x0D37,
+ "GL_MAX_PROJECTION_STACK_DEPTH":0x0D38,
+ "GL_MAX_TEXTURE_STACK_DEPTH":0x0D39,
+ "GL_MAX_VIEWPORT_DIMS":0x0D3A,
+ "GL_MAX_CLIENT_ATTRIB_STACK_DEPTH":0x0D3B,
+ "GL_SUBPIXEL_BITS":0x0D50,
+ "GL_INDEX_BITS":0x0D51,
+ "GL_RED_BITS":0x0D52,
+ "GL_GREEN_BITS":0x0D53,
+ "GL_BLUE_BITS":0x0D54,
+ "GL_ALPHA_BITS":0x0D55,
+ "GL_DEPTH_BITS":0x0D56,
+ "GL_STENCIL_BITS":0x0D57,
+ "GL_ACCUM_RED_BITS":0x0D58,
+ "GL_ACCUM_GREEN_BITS":0x0D59,
+ "GL_ACCUM_BLUE_BITS":0x0D5A,
+ "GL_ACCUM_ALPHA_BITS":0x0D5B,
+ "GL_NAME_STACK_DEPTH":0x0D70,
+ "GL_AUTO_NORMAL":0x0D80,
+ "GL_MAP1_COLOR_4":0x0D90,
+ "GL_MAP1_INDEX":0x0D91,
+ "GL_MAP1_NORMAL":0x0D92,
+ "GL_MAP1_TEXTURE_COORD_1":0x0D93,
+ "GL_MAP1_TEXTURE_COORD_2":0x0D94,
+ "GL_MAP1_TEXTURE_COORD_3":0x0D95,
+ "GL_MAP1_TEXTURE_COORD_4":0x0D96,
+ "GL_MAP1_VERTEX_3":0x0D97,
+ "GL_MAP1_VERTEX_4":0x0D98,
+ "GL_MAP2_COLOR_4":0x0DB0,
+ "GL_MAP2_INDEX":0x0DB1,
+ "GL_MAP2_NORMAL":0x0DB2,
+ "GL_MAP2_TEXTURE_COORD_1":0x0DB3,
+ "GL_MAP2_TEXTURE_COORD_2":0x0DB4,
+ "GL_MAP2_TEXTURE_COORD_3":0x0DB5,
+ "GL_MAP2_TEXTURE_COORD_4":0x0DB6,
+ "GL_MAP2_VERTEX_3":0x0DB7,
+ "GL_MAP2_VERTEX_4":0x0DB8,
+ "GL_MAP1_GRID_DOMAIN":0x0DD0,
+ "GL_MAP1_GRID_SEGMENTS":0x0DD1,
+ "GL_MAP2_GRID_DOMAIN":0x0DD2,
+ "GL_MAP2_GRID_SEGMENTS":0x0DD3,
+ "GL_TEXTURE_1D":0x0DE0,
+ "GL_TEXTURE_2D":0x0DE1,
+ "GL_FEEDBACK_BUFFER_POINTER":0x0DF0,
+ "GL_FEEDBACK_BUFFER_SIZE":0x0DF1,
+ "GL_FEEDBACK_BUFFER_TYPE":0x0DF2,
+ "GL_SELECTION_BUFFER_POINTER":0x0DF3,
+ "GL_SELECTION_BUFFER_SIZE":0x0DF4,
+ "GL_TEXTURE_WIDTH":0x1000,
+ "GL_TEXTURE_HEIGHT":0x1001,
+ "GL_TEXTURE_INTERNAL_FORMAT":0x1003,
+ "GL_TEXTURE_BORDER_COLOR":0x1004,
+ "GL_TEXTURE_BORDER":0x1005,
+ "GL_DONT_CARE":0x1100,
+ "GL_FASTEST":0x1101,
+ "GL_NICEST":0x1102,
+ "GL_LIGHT0":0x4000,
+ "GL_LIGHT1":0x4001,
+ "GL_LIGHT2":0x4002,
+ "GL_LIGHT3":0x4003,
+ "GL_LIGHT4":0x4004,
+ "GL_LIGHT5":0x4005,
+ "GL_LIGHT6":0x4006,
+ "GL_LIGHT7":0x4007,
+ "GL_AMBIENT":0x1200,
+ "GL_DIFFUSE":0x1201,
+ "GL_SPECULAR":0x1202,
+ "GL_POSITION":0x1203,
+ "GL_SPOT_DIRECTION":0x1204,
+ "GL_SPOT_EXPONENT":0x1205,
+ "GL_SPOT_CUTOFF":0x1206,
+ "GL_CONSTANT_ATTENUATION":0x1207,
+ "GL_LINEAR_ATTENUATION":0x1208,
+ "GL_QUADRATIC_ATTENUATION":0x1209,
+ "GL_COMPILE":0x1300,
+ "GL_COMPILE_AND_EXECUTE":0x1301,
+ "GL_CLEAR":0x1500,
+ "GL_AND":0x1501,
+ "GL_AND_REVERSE":0x1502,
+ "GL_COPY":0x1503,
+ "GL_AND_INVERTED":0x1504,
+ "GL_NOOP":0x1505,
+ "GL_XOR":0x1506,
+ "GL_OR":0x1507,
+ "GL_NOR":0x1508,
+ "GL_EQUIV":0x1509,
+ "GL_INVERT":0x150A,
+ "GL_OR_REVERSE":0x150B,
+ "GL_COPY_INVERTED":0x150C,
+ "GL_OR_INVERTED":0x150D,
+ "GL_NAND":0x150E,
+ "GL_SET":0x150F,
+ "GL_EMISSION":0x1600,
+ "GL_SHININESS":0x1601,
+ "GL_AMBIENT_AND_DIFFUSE":0x1602,
+ "GL_COLOR_INDEXES":0x1603,
+ "GL_MODELVIEW":0x1700,
+ "GL_PROJECTION":0x1701,
+ "GL_TEXTURE":0x1702,
+ "GL_COLOR":0x1800,
+ "GL_DEPTH":0x1801,
+ "GL_STENCIL":0x1802,
+ "GL_COLOR_INDEX":0x1900,
+ "GL_STENCIL_INDEX":0x1901,
+ "GL_DEPTH_COMPONENT":0x1902,
+ "GL_RED":0x1903,
+ "GL_GREEN":0x1904,
+ "GL_BLUE":0x1905,
+ "GL_ALPHA":0x1906,
+ "GL_RGB":0x1907,
+ "GL_RGBA":0x1908,
+ "GL_LUMINANCE":0x1909,
+ "GL_LUMINANCE_ALPHA":0x190A,
+ "GL_BITMAP":0x1A00,
+ "GL_POINT":0x1B00,
+ "GL_LINE":0x1B01,
+ "GL_FILL":0x1B02,
+ "GL_RENDER":0x1C00,
+ "GL_FEEDBACK":0x1C01,
+ "GL_SELECT":0x1C02,
+ "GL_FLAT":0x1D00,
+ "GL_SMOOTH":0x1D01,
+ "GL_KEEP":0x1E00,
+ "GL_REPLACE":0x1E01,
+ "GL_INCR":0x1E02,
+ "GL_DECR":0x1E03,
+ "GL_VENDOR":0x1F00,
+ "GL_RENDERER":0x1F01,
+ "GL_VERSION":0x1F02,
+ "GL_EXTENSIONS":0x1F03,
+ "GL_S":0x2000,
+ "GL_T":0x2001,
+ "GL_R":0x2002,
+ "GL_Q":0x2003,
+ "GL_MODULATE":0x2100,
+ "GL_DECAL":0x2101,
+ "GL_TEXTURE_ENV_MODE":0x2200,
+ "GL_TEXTURE_ENV_COLOR":0x2201,
+ "GL_TEXTURE_ENV":0x2300,
+ "GL_EYE_LINEAR":0x2400,
+ "GL_OBJECT_LINEAR":0x2401,
+ "GL_SPHERE_MAP":0x2402,
+ "GL_TEXTURE_GEN_MODE":0x2500,
+ "GL_OBJECT_PLANE":0x2501,
+ "GL_EYE_PLANE":0x2502,
+ "GL_NEAREST":0x2600,
+ "GL_LINEAR":0x2601,
+ "GL_NEAREST_MIPMAP_NEAREST":0x2700,
+ "GL_LINEAR_MIPMAP_NEAREST":0x2701,
+ "GL_NEAREST_MIPMAP_LINEAR":0x2702,
+ "GL_LINEAR_MIPMAP_LINEAR":0x2703,
+ "GL_TEXTURE_MAG_FILTER":0x2800,
+ "GL_TEXTURE_MIN_FILTER":0x2801,
+ "GL_TEXTURE_WRAP_S":0x2802,
+ "GL_TEXTURE_WRAP_T":0x2803,
+ "GL_CLAMP":0x2900,
+ "GL_REPEAT":0x2901,
+ "GL_CLIENT_PIXEL_STORE_BIT":0x00000001,
+ "GL_CLIENT_VERTEX_ARRAY_BIT":0x00000002,
+ "GL_CLIENT_ALL_ATTRIB_BITS":0xffffffff,
+ "GL_POLYGON_OFFSET_FACTOR":0x8038,
+ "GL_POLYGON_OFFSET_UNITS":0x2A00,
+ "GL_POLYGON_OFFSET_POINT":0x2A01,
+ "GL_POLYGON_OFFSET_LINE":0x2A02,
+ "GL_POLYGON_OFFSET_FILL":0x8037,
+ "GL_ALPHA4":0x803B,
+ "GL_ALPHA8":0x803C,
+ "GL_ALPHA12":0x803D,
+ "GL_ALPHA16":0x803E,
+ "GL_LUMINANCE4":0x803F,
+ "GL_LUMINANCE8":0x8040,
+ "GL_LUMINANCE12":0x8041,
+ "GL_LUMINANCE16":0x8042,
+ "GL_LUMINANCE4_ALPHA4":0x8043,
+ "GL_LUMINANCE6_ALPHA2":0x8044,
+ "GL_LUMINANCE8_ALPHA8":0x8045,
+ "GL_LUMINANCE12_ALPHA4":0x8046,
+ "GL_LUMINANCE12_ALPHA12":0x8047,
+ "GL_LUMINANCE16_ALPHA16":0x8048,
+ "GL_INTENSITY":0x8049,
+ "GL_INTENSITY4":0x804A,
+ "GL_INTENSITY8":0x804B,
+ "GL_INTENSITY12":0x804C,
+ "GL_INTENSITY16":0x804D,
+ "GL_R3_G3_B2":0x2A10,
+ "GL_RGB4":0x804F,
+ "GL_RGB5":0x8050,
+ "GL_RGB8":0x8051,
+ "GL_RGB10":0x8052,
+ "GL_RGB12":0x8053,
+ "GL_RGB16":0x8054,
+ "GL_RGBA2":0x8055,
+ "GL_RGBA4":0x8056,
+ "GL_RGB5_A1":0x8057,
+ "GL_RGBA8":0x8058,
+ "GL_RGB10_A2":0x8059,
+ "GL_RGBA12":0x805A,
+ "GL_RGBA16":0x805B,
+ "GL_TEXTURE_RED_SIZE":0x805C,
+ "GL_TEXTURE_GREEN_SIZE":0x805D,
+ "GL_TEXTURE_BLUE_SIZE":0x805E,
+ "GL_TEXTURE_ALPHA_SIZE":0x805F,
+ "GL_TEXTURE_LUMINANCE_SIZE":0x8060,
+ "GL_TEXTURE_INTENSITY_SIZE":0x8061,
+ "GL_PROXY_TEXTURE_1D":0x8063,
+ "GL_PROXY_TEXTURE_2D":0x8064,
+ "GL_TEXTURE_PRIORITY":0x8066,
+ "GL_TEXTURE_RESIDENT":0x8067,
+ "GL_TEXTURE_BINDING_1D":0x8068,
+ "GL_TEXTURE_BINDING_2D":0x8069,
+ "GL_VERTEX_ARRAY":0x8074,
+ "GL_NORMAL_ARRAY":0x8075,
+ "GL_COLOR_ARRAY":0x8076,
+ "GL_INDEX_ARRAY":0x8077,
+ "GL_TEXTURE_COORD_ARRAY":0x8078,
+ "GL_EDGE_FLAG_ARRAY":0x8079,
+ "GL_VERTEX_ARRAY_SIZE":0x807A,
+ "GL_VERTEX_ARRAY_TYPE":0x807B,
+ "GL_VERTEX_ARRAY_STRIDE":0x807C,
+ "GL_NORMAL_ARRAY_TYPE":0x807E,
+ "GL_NORMAL_ARRAY_STRIDE":0x807F,
+ "GL_COLOR_ARRAY_SIZE":0x8081,
+ "GL_COLOR_ARRAY_TYPE":0x8082,
+ "GL_COLOR_ARRAY_STRIDE":0x8083,
+ "GL_INDEX_ARRAY_TYPE":0x8085,
+ "GL_INDEX_ARRAY_STRIDE":0x8086,
+ "GL_TEXTURE_COORD_ARRAY_SIZE":0x8088,
+ "GL_TEXTURE_COORD_ARRAY_TYPE":0x8089,
+ "GL_TEXTURE_COORD_ARRAY_STRIDE":0x808A,
+ "GL_EDGE_FLAG_ARRAY_STRIDE":0x808C,
+ "GL_VERTEX_ARRAY_POINTER":0x808E,
+ "GL_NORMAL_ARRAY_POINTER":0x808F,
+ "GL_COLOR_ARRAY_POINTER":0x8090,
+ "GL_INDEX_ARRAY_POINTER":0x8091,
+ "GL_TEXTURE_COORD_ARRAY_POINTER":0x8092,
+ "GL_EDGE_FLAG_ARRAY_POINTER":0x8093,
+ "GL_V2F":0x2A20,
+ "GL_V3F":0x2A21,
+ "GL_C4UB_V2F":0x2A22,
+ "GL_C4UB_V3F":0x2A23,
+ "GL_C3F_V3F":0x2A24,
+ "GL_N3F_V3F":0x2A25,
+ "GL_C4F_N3F_V3F":0x2A26,
+ "GL_T2F_V3F":0x2A27,
+ "GL_T4F_V4F":0x2A28,
+ "GL_T2F_C4UB_V3F":0x2A29,
+ "GL_T2F_C3F_V3F":0x2A2A,
+ "GL_T2F_N3F_V3F":0x2A2B,
+ "GL_T2F_C4F_N3F_V3F":0x2A2C,
+ "GL_T4F_C4F_N3F_V4F":0x2A2D,
+ "GL_EXT_texture3D":1,
+ "GL_EXT_rescale_normal":1,
+ "GL_SGI_color_table":1,
+ "GL_SGI_texture_color_table":1,
+ "GL_SUNX_geometry_compression":1,
+ "GL_EXT_abgr":1,
+ "GL_SUNX_surface_hint":1,
+ "GL_SUN_multi_draw_arrays":1,
+ "GL_HP_occlusion_test":1,
+ "GL_PACK_SKIP_IMAGES_EXT":0x806B,
+ "GL_PACK_IMAGE_HEIGHT_EXT":0x806C,
+ "GL_UNPACK_SKIP_IMAGES_EXT":0x806D,
+ "GL_UNPACK_IMAGE_HEIGHT_EXT":0x806E,
+ "GL_TEXTURE_3D_EXT":0x806F,
+ "GL_PROXY_TEXTURE_3D_EXT":0x8070,
+ "GL_TEXTURE_DEPTH_EXT":0x8071,
+ "GL_TEXTURE_WRAP_R_EXT":0x8072,
+ "GL_MAX_3D_TEXTURE_SIZE_EXT":0x8073,
+ "GL_TEXTURE_COLOR_TABLE_SGI":0x80BC,
+ "GL_PROXY_TEXTURE_COLOR_TABLE_SGI":0x80BD,
+ "GL_COLOR_TABLE_SGI":0x80D0,
+ "GL_PROXY_COLOR_TABLE_SGI":0x80D3,
+ "GL_COLOR_TABLE_SCALE_SGI":0x80D6,
+ "GL_COLOR_TABLE_BIAS_SGI":0x80D7,
+ "GL_COLOR_TABLE_FORMAT_SGI":0x80D8,
+ "GL_COLOR_TABLE_WIDTH_SGI":0x80D9,
+ "GL_COLOR_TABLE_RED_SIZE_SGI":0x80DA,
+ "GL_COLOR_TABLE_GREEN_SIZE_SGI":0x80DB,
+ "GL_COLOR_TABLE_BLUE_SIZE_SGI":0x80DC,
+ "GL_COLOR_TABLE_ALPHA_SIZE_SGI":0x80DD,
+ "GL_COLOR_TABLE_LUMINANCE_SIZE_SGI":0x80DE,
+ "GL_COLOR_TABLE_INTENSITY_SIZE_SGI":0x80DF,
+ "GL_POST_CONVOLUTION_COLOR_TABLE_SGI":0x80D1,
+ "GL_PROXY_COLOR_TABLE_SGI":0x80D3,
+ "GL_PROXY_POST_CONVOLUTION_COLOR_TABLE_SGI":0x80D4,
+ "GL_COLOR_TABLE_SCALE_SGI":0x80D6,
+ "GL_COLOR_TABLE_BIAS_SGI":0x80D7,
+ "GL_COLOR_TABLE_FORMAT_SGI":0x80D8,
+ "GL_COLOR_TABLE_WIDTH_SGI":0x80D9,
+ "GL_COLOR_TABLE_RED_SIZE_SGI":0x80DA,
+ "GL_COLOR_TABLE_GREEN_SIZE_SGI":0x80DB,
+ "GL_COLOR_TABLE_BLUE_SIZE_SGI":0x80DC,
+ "GL_COLOR_TABLE_ALPHA_SIZE_SGI":0x80DD,
+ "GL_COLOR_TABLE_LUMINANCE_SIZE_SGI":0x80DE,
+ "GL_COLOR_TABLE_INTENSITY_SIZE_SGI":0x80DF,
+ "GL_COMPRESSED_GEOM_ACCELERATED_SUNX":0x81D0,
+ "GL_COMPRESSED_GEOM_VERSION_SUNX":0x81D1,
+ "GL_SURFACE_SIZE_HINT_SUNX":0x81D2,
+ "GL_LARGE_SUNX":0x81D3,
+ "GL_OCCLUSION_TEST_HP":0x8165,
+ "GL_OCCLUSION_RESULT_HP":0x8166,
+ "GL_RESCALE_NORMAL_EXT":0x803A,
+ "GL_ABGR_EXT":0x8000,
+ "GL_EXT_blend_color":1,
+ "GL_EXT_blend_minmax":1,
+ "GL_EXT_blend_subtract":1,
+ "GL_CONSTANT_COLOR_EXT":0x8001,
+ "GL_ONE_MINUS_CONSTANT_COLOR_EXT":0x8002,
+ "GL_CONSTANT_ALPHA_EXT":0x8003,
+ "GL_ONE_MINUS_CONSTANT_ALPHA_EXT":0x8004,
+ "GL_BLEND_COLOR_EXT":0x8005,
+ "GL_FUNC_ADD_EXT":0x8006,
+ "GL_MIN_EXT":0x8007,
+ "GL_MAX_EXT":0x8008,
+ "GL_BLEND_EQUATION_EXT":0x8009,
+ "GL_FUNC_SUBTRACT_EXT":0x800A,
+ "GL_FUNC_REVERSE_SUBTRACT_EXT":0x800B,
+ "GL_LOGIC_OP":0x0BF1,
+ "GL_TEXTURE_COMPONENTS":0x1003,
+ "GL_CONVOLUTION_1D_EXT":0x8010,
+ "GL_CONVOLUTION_2D_EXT":0x8011,
+ "GL_SEPARABLE_2D_EXT":0x8012,
+ "GL_CONVOLUTION_BORDER_MODE_EXT":0x8013,
+ "GL_CONVOLUTION_FILTER_SCALE_EXT":0x8014,
+ "GL_CONVOLUTION_FILTER_BIAS_EXT":0x8015,
+ "GL_REDUCE_EXT":0x8016,
+ "GL_CONVOLUTION_FORMAT_EXT":0x8017,
+ "GL_CONVOLUTION_WIDTH_EXT":0x8018,
+ "GL_CONVOLUTION_HEIGHT_EXT":0x8019,
+ "GL_MAX_CONVOLUTION_WIDTH_EXT":0x801A,
+ "GL_MAX_CONVOLUTION_HEIGHT_EXT":0x801B,
+ "GL_POST_CONVOLUTION_RED_SCALE_EXT":0x801C,
+ "GL_POST_CONVOLUTION_GREEN_SCALE_EXT":0x801D,
+ "GL_POST_CONVOLUTION_BLUE_SCALE_EXT":0x801E,
+ "GL_POST_CONVOLUTION_ALPHA_SCALE_EXT":0x801F,
+ "GL_POST_CONVOLUTION_RED_BIAS_EXT":0x8020,
+ "GL_POST_CONVOLUTION_GREEN_BIAS_EXT":0x8021,
+ "GL_POST_CONVOLUTION_BLUE_BIAS_EXT":0x8022,
+ "GL_POST_CONVOLUTION_ALPHA_BIAS_EXT":0x8023,
+ "GL_HP_convolution_border_modes":1,
+ "GL_SUN_convolution_border_modes":1,
+ "GL_IGNORE_BORDER_HP":0x8150,
+ "GL_CONSTANT_BORDER_HP":0x8151,
+ "GL_WRAP_BORDER_SUN":0x81D4,
+ "GL_REPLICATE_BORDER_HP":0x8153,
+ "GL_CONVOLUTION_BORDER_COLOR_HP":0x8154,
+ "GL_EXT_histogram":1,
+ "GL_HISTOGRAM_EXT":0x8024,
+ "GL_PROXY_HISTOGRAM_EXT":0x8025,
+ "GL_HISTOGRAM_WIDTH_EXT":0x8026,
+ "GL_HISTOGRAM_FORMAT_EXT":0x8027,
+ "GL_HISTOGRAM_RED_SIZE_EXT":0x8028,
+ "GL_HISTOGRAM_GREEN_SIZE_EXT":0x8029,
+ "GL_HISTOGRAM_BLUE_SIZE_EXT":0x802A,
+ "GL_HISTOGRAM_ALPHA_SIZE_EXT":0x802B,
+ "GL_HISTOGRAM_LUMINANCE_SIZE_EXT":0x802C,
+ "GL_HISTOGRAM_SINK_EXT":0x802D,
+ "GL_MINMAX_EXT":0x802E,
+ "GL_MINMAX_FORMAT_EXT":0x802F,
+ "GL_MINMAX_SINK_EXT":0x8030,
+ "GL_TABLE_TOO_LARGE_EXT":0x8031,
+ "GL_EXT_pixel_transform":1,
+ "GL_PIXEL_TRANSFORM_2D_EXT":0x8330,
+ "GL_PIXEL_MAG_FILTER_EXT":0x8331,
+ "GL_PIXEL_MIN_FILTER_EXT":0x8332,
+ "GL_PIXEL_CUBIC_WEIGHT_EXT":0x8333,
+ "GL_CUBIC_EXT":0x8334,
+ "GL_AVERAGE_EXT":0x8335,
+ "GL_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT":0x8336,
+ "GL_MAX_PIXEL_TRANSFORM_2D_STACK_DEPTH_EXT":0x8337,
+ "GL_PIXEL_TRANSFORM_2D_MATRIX_EXT":0x8338,
+ "GL_PIXEL_TRANSFORM_COLOR_TABLE_EXT":0x8339,
+ "GL_PROXY_PIXEL_TRANSFORM_COLOR_TABLE_EXT":0x833A,
+]);
diff --git a/src/post_modules/GL/features.pike b/src/post_modules/GL/features.pike
new file mode 100644
index 0000000000000000000000000000000000000000..9ab0452daed551924e5545307df8232658489f52
--- /dev/null
+++ b/src/post_modules/GL/features.pike
@@ -0,0 +1,156 @@
+array funcEV = ({
+  "glBegin",
+  "glCullFace",
+  "glDepthFunc",
+  "glDisable",
+  "glDisableClientState",
+  "glDrawBuffer",
+  "glEnable",
+  "glEnableClientState",
+  "glFrontFace",
+  "glLogicOp",
+  "glMatrixMode",
+  "glReadBuffer",
+  "glRenderMode",
+  "glShadeModel",
+});
+array funcV = ({
+  "glEnd",
+  "glEndList",
+  "glFinish",
+  "glFlush",
+  "glInitNames",
+  "glLoadIdentity",
+  "glPopAttrib",
+  "glPopClientAttrib",
+  "glPopMatrix",
+  "glPopName",
+  "glPushMatrix",
+});
+array func_misc = ({
+  ({"glAccum", "VEF"}),
+  ({"glAlphaFunc", "VEF"}),
+  ({"glArrayElement", "VI"}),
+  ({"glBindTexture","VEI"}),
+  ({"glBlendFunc", "VEE"}),
+  ({"glCallList","VI"}),
+  ({"glClear","VB"}),
+  ({"glClearAccum", "V+FFFF"}),
+  ({"glClearColor", "V+FFFF"}),
+  ({"glClearDepth", "VD"}),
+  ({"glClearIndex", "VF"}),
+  ({"glClearStencil", "VI"}),
+  ({"glClipPlane", "VE=DDDD"}),
+  ({"glColor", "V+ZZZZ"}),
+  ({"glColorMask", "VOOOO"}),
+  ({"glColorMaterial", "VEE"}),
+  ({"glCopyPixels", "VIIIIE"}),
+  ({"glCopyTexImage1D", "VEIEIIII"}),
+  ({"glCopyTexImage2D", "VEIEIIIII"}),
+  ({"glCopyTexSubImage1D", "VEIIIII"}),
+  ({"glCopyTexSubImage2D", "VEIIIIIII"}),
+  ({"glDeleteLists", "VII"}),
+  ({"glDepthMask", "VO"}),
+  ({"glDepthRange", "VDD"}),
+  ({"glDrawArrays", "VEII"}),
+  ({"glDrawPixels", "Vwhfti"}),
+  ({"glEdgeFlag", "VO"}),
+  ({"glEvalCoord", "V+RR"}),
+  ({"glEvalPoint", "V+II"}),
+  ({"glFog","VE@Q"}),
+  ({"glFrustum", "VDDDDDD"}),
+  ({"glGenLists", "II"}),
+  ({"glGetError", "E"}),
+  ({"glGetString", "SE"}),
+  ({"glHint", "VEE"}),
+  ({"glIndex", "VZ"}),
+  ({"glIndexMask", "VI"}),
+  ({"glIsEnabled", "OE"}),
+  ({"glIsList", "OI"}),
+  ({"glIsTexture", "OI"}),
+  ({"glLight", "VEE@Q"}),
+  ({"glLightModel", "VE@Q"}),
+  ({"glLineStipple", "VII"}),
+  ({"glLineWidth", "VF"}),
+  ({"glListBase", "VI"}),
+  ({"glLoadMatrix", "V[16R"}),
+  ({"glLoadName", "VI"}),
+  ({"glMaterial", "VEE@Q"}),
+  ({"glMultMatrix", "V[16R"}),
+  ({"glNewList", "VIE"}),
+  ({"glNormal", "V#ZZZ"}),
+  ({"glOrtho", "VDDDDDD"}),
+  ({"glPassThrough", "VF"}),
+  ({"glPixelZoom", "VFF"}),
+  ({"glPointSize", "VF"}),
+  ({"glPolygonMode", "VEE"}),
+  ({"glPolygonOffset", "VFF"}),
+  ({"glPushAttrib", "VB"}),
+  ({"glPushClientAttrib", "VB"}),
+  ({"glPushName", "VI"}),
+  ({"glRasterPos", "V+ZZZ"}),
+  ({"glRotate", "V!RRRR"}),
+  ({"glScale", "V!RRR"}),
+  ({"glScissor", "VIIII"}),
+  ({"glStencilFunc", "VEII"}),
+  ({"glStencilMask", "VI"}),
+  ({"glStencilOp", "VEEE"}),
+  ({"glTexCoord", "V+Z"}),
+  ({"glTexEnv","VEE@Q"}),
+  ({"glTexGen","VEE@Z"}),
+  ({"glTexImage2D","VEIIwhIfti"}),
+  ({"glTexParameter","VEE@Q"}),
+  ({"glTexSubImage2D","VEIIIwhfti"}),
+  ({"glTranslate", "V!RRR"}),
+  ({"glVertex","V+ZZZ"}),
+  ({"glViewport", "VIIII"}),
+});
+mapping func_cat = ([
+  "VE":funcEV,
+  "V":funcV,
+]);
+
+/*
+  Not implemented:
+
+  glAreTexturesResident
+  glBitmap
+  glCallLists
+  glColorPointer
+  glDeleteTextures
+  glDrawElements
+  glEdgeFlagPointer
+  glEvalMesh
+  glFeedbackBuffer
+  glGenTextures
+  glGetClipPlane
+  glGetLight
+  glGetMap
+  glGetMaterial
+  glGetPixelMap
+  glGetPointer
+  glGetPolygonStipple
+  glGetTexEnv
+  glGetTexGen
+  glGetTexImage
+  glGetTexLevelParameter
+  glGetTexParameter
+  glIndexPointer
+  glInterleavedArrays
+  glMap1
+  glMap2
+  glMapGrid
+  glNormalPointer
+  glPixelMap
+  glPixelTransfer
+  glPolygonStipple
+  glPrioritizeTextures
+  glReadPixels
+  glRect
+  glSelectBuffer
+  glTexCoordPointer
+  glTexImage1D
+  glTexSubImage1D
+  glVertexPoint
+
+*/
diff --git a/src/post_modules/GL/gen.pike b/src/post_modules/GL/gen.pike
new file mode 100755
index 0000000000000000000000000000000000000000..9c03fee07805fad5a17e865afadbc19022043f11
--- /dev/null
+++ b/src/post_modules/GL/gen.pike
@@ -0,0 +1,438 @@
+#!/usr/local/bin/pike
+/*
+   V=void
+   I=int
+   D=double
+   F=float
+   E=enum
+   B=bitfield
+   O=bool
+   R=double/float
+   Q=int/float
+   Z=(byte/)double/float/int/short
+
+   +XXXX = 3/4/array(3/4)
+   +XXX  = 2/3/4/array(2/3/4)
+   +XX   = 1/2/array(1/2)
+   +X    = 1/2/3/4/array(1/2/3/4)
+   =XXXX = 4/array(4)
+   =XXX  = 3/array(3)
+   @X    = 1/array(n)
+   [nnX  = array(nn)
+
+   #     = like =, but add count
+   !     = like =, but no vector version available
+
+   image object support:
+
+   w     = width of image
+   h     = height of image
+   f     = format of image
+   t     = type of image
+   i     = image data
+
+*/
+
+inherit "features";
+inherit "constants";
+
+void error(string msg, mixed ... args)
+{
+  if(sizeof(args))
+    msg = sprintf(msg, @args);
+  werror(msg+"\n");
+  exit(1);
+}
+
+array(string|array(string)) special_234(int mi, int mx, string ty, int|void a)
+{
+  string tm="BIT_FLOAT|BIT_INT", baset="float|int", rt="if";
+  array(string) typ=({});
+  int i, ad;
+  if(sizeof(Array.uniq(values(ty)))!=1)
+    error("Unparsable 234 type '%s'.", ty);
+  switch(ty[0]) {
+  case 'E':
+  case 'B':
+  case 'I':
+  case 'O':
+    baset="int";
+    tm="BIT_INT";
+    rt="i";
+    break;
+  case 'D':
+    ad=1;  /* fallthrough */
+  case 'F':
+    baset="float";
+    tm="BIT_FLOAT";
+    rt=(ad?"":"f");
+    break;
+  case 'R':
+    rt="f";
+  case 'Z':
+    ad=1;
+    break;
+  case 'Q':
+    break;
+  default:
+    error("Unknown 234 type '%s'.", ty[0..0]);
+  }
+  if(ad)
+    rt+="d";
+  if(a)
+    typ+=({"array("+baset+")"});
+  else for(i=0; i<mx; i++) {
+    string t = baset;
+    if(!i)
+      t+="|array("+baset+")";
+    if(i>=mi || i>0)
+      t+="|void";
+    typ+=({t});
+  }
+  return ({typ,tm,rows((['i':"ZT_INT",'f':"ZT_FLOAT",'d':"ZT_DOUBLE"]),
+		       values(rt))*"|",rt});
+}
+
+array(string) gen_func(string name, string ty)
+{
+  string res="", got="", prot, vdec, vret, vcast, fu=name;
+  array novec, args=({}), argt=({});
+  int r234, argt_cut=-1, img_obj=0, polya=-1;
+  string rtypes;
+
+  switch(ty[0]) {
+  case 'V':
+    prot=":void";
+    break;
+  case 'I':
+  case 'O':
+  case 'E':
+    prot=":int";
+    vdec="INT32";
+    vret="push_int";
+    break;
+  case 'S':
+    prot=":string";
+    vdec="const GLubyte *";
+    vret="push_text";
+    vcast="(char *)";
+    break;
+  default:
+    error("%s: Unknown return type '%c'.", name, ty[0]);
+  }
+
+  res += "static void f_"+name+"(INT32 args)\n{\n"+
+    (vdec?("  "+vdec+" res;\n"):"");
+
+  int a=1;
+  for(int i=1; i<sizeof(ty); i++)
+    switch(ty[i]) {
+    case 'B':
+    case 'E':
+    case 'O':
+    case 'I':
+      argt += ({"int"});
+      args += ({ "arg"+a });
+      res += "  INT32 arg"+a+";\n";
+      got += "  arg"+a+"=sp["+(a-1)+"-args].u.integer;\n";
+      a++;
+      break;
+    case 'D':
+      argt += ({"float"});
+      args += ({ "arg"+a });
+      res += "  double arg"+a+";\n";
+      got += "  arg"+a+"=sp["+(a-1)+"-args].u.float_number;\n";
+      a++;
+      break;
+    case 'F':
+      argt += ({"float"});
+      args += ({ "arg"+a });
+      res += "  float arg"+a+";\n";
+      got += "  arg"+a+"=sp["+(a-1)+"-args].u.float_number;\n";
+      a++;
+      break;
+    case 'Z':
+      argt += ({"float|int"});
+      args += ({ "sp["+(a-1)+"-args]" });
+      polya = (a++)-1;
+      break;
+    case '+':
+      int mi, mx;
+      switch(sizeof(ty[i+1..])) {
+      case 1:
+	mi = 1; mx = 4; break;
+      case 2:
+	mi = 1; mx = 2; break;
+      case 3:
+	mi = 2; mx = 4; break;
+      case 4:
+	mi = 3; mx = 4; break;
+      default:
+	error("Can't understand + followed by %d chars.\n", sizeof(ty[i+1..]));
+      }
+      array plusfix = special_234(mi, mx, ty[i+1..]);
+      res += "  struct zvalue4 zv4;\n";
+      argt_cut = sizeof(argt);
+      argt += plusfix[0];
+      res += "\n  int r234=check_234_args(\""+name+"\", args-"+(a-1)+", "+
+	mi+", "+mx+", "+plusfix[1]+", "+plusfix[2]+", &zv4);\n";
+      r234=1;
+      rtypes=plusfix[3];
+      i=sizeof(ty);
+      novec=indices(allocate(mx+1))[mi..];
+      break;
+    case '#':
+      fu += sizeof(ty[i+1..]);
+      /* fallthrough */
+    case '!':
+    case '=':
+      array eqfix = special_234(sizeof(ty[i+1..]), sizeof(ty[i+1..]),
+				ty[i+1..]);
+      res += "  struct zvalue4 zv4;\n";
+      argt_cut = sizeof(argt);
+      argt += eqfix[0];
+      res += "\n  check_234_args(\""+name+"\", args-"+(a-1)+", "+
+	sizeof(ty[i+1..])+", "+sizeof(ty[i+1..])+", "+eqfix[1]+", "+
+	eqfix[2]+", &zv4);\n";
+      r234=2;
+      rtypes=eqfix[3];
+      if(ty[i]=='!')
+	novec=indices(ty[i+1..]);
+      i=sizeof(ty);
+      break;
+    case '@':
+      array atfix = special_234(1, 1, ty[i+1..]);
+      res += "  union zvalue16 zv16;\n";
+      argt_cut = sizeof(argt);
+      argt += atfix[0];
+      res += "\n  int r1n=check_1n_args(\""+name+"\", args-"+(a-1)+", "+
+	atfix[1]+", "+atfix[2]+", &zv16);\n";
+      r234=3;
+      rtypes=atfix[3];
+      i=sizeof(ty);
+      break;
+    case '[':
+      int nn;
+      string rst;
+      sscanf(ty[i+1..], "%d%s", nn, rst);
+      array arrfix = special_234(nn, nn, rst, 1);
+      res += "  union zvalue16 zv16;\n  int r1n;\n";
+      argt += arrfix[0];
+      got += "  if(sp["+(a-1)+"-args].u.array->size != "+nn+")\n"
+	"    error(\""+name+": Array length is wrong (is %d, should be "+nn+
+	")\\n\", sp["+(a-1)+"-args].u.array->size);\n\n";
+      got += "  r1n=check_1n_args(\""+name+"\", args-"+(a-1)+", "+
+	arrfix[1]+", "+arrfix[2]+", &zv16);\n";
+      r234=-1;
+      rtypes=arrfix[3];
+      i=sizeof(ty);
+      break;
+    case 'w':
+      img_obj=1;
+      args += ({ "img.width" });
+      break;
+    case 'h':
+      img_obj=1;
+      args += ({ "img.height" });
+      break;
+    case 'f':
+      img_obj=1;
+      args += ({ "img.format" });
+      break;
+    case 't':
+      img_obj=1;
+      args += ({ "img.type" });
+      break;
+    case 'i':
+      img_obj=1;
+      args += ({ "img.pixels" });
+      break;
+
+    default:
+      error("%s: Unknown parameter type '%c'.", name, ty[i]);
+    }
+
+  if(img_obj) {
+    argt += ({"object|mapping(string:object)"});
+    res += "  struct zimage img;\n";
+    got += "  check_img_arg(&sp["+(a-1)+"-args], &img, "+a+
+      ", \""+name+"\");\n";
+  }
+
+  prot = (argt*",")+prot;
+
+  if(sizeof(argt))
+    res += "\n  check_all_args(\""+name+"\", args, "+
+      ((Array.map((argt_cut<0?argt:argt[..argt_cut-1]),
+		  lambda(string t) {
+		    string t2;
+		    while(3==sscanf(t, "%s(%*s)%s", t, t2))
+		      t+=t2;
+		    return Array.map(t/"|",
+				     lambda(string t) {
+				       return "BIT_"+upper_case(t);
+				     })*"|";
+		  }))+
+       (r234>0?({"BIT_MANY|BIT_MIXED|BIT_VOID"}):({}))+({"0"}))*", "+");\n";
+
+  if(sizeof(got))
+    res += "\n"+got+"\n";
+
+  switch(r234)
+  {
+  case 0:
+    if(polya<0)
+      res += (vret?"  res=":"  ")+fu+"("+(args*",")+");\n";
+    else
+      res += "  switch("+args[polya]+".type) {\n"+
+	Array.map(argt[polya]/"|", lambda(string t) 
+				   {
+				     array(string) a = copy_value(args);
+				     a[polya] += ".u";
+				     switch(t) {
+				     case "int":
+				       a[polya]+=".integer"; break;
+				     case "float":
+				       a[polya]+=".float_number"; break;
+				     }
+				     return "    case T_"+upper_case(t)+": "+
+				       (vret?"res=":"")+fu+t[0..0]+"("+
+				       (a*",")+"); break;\n";
+				   })*""+"  }\n";
+    break;
+  case 1:
+    if(sizeof(rtypes)==1)
+      res += "  switch(r234) {\n"+Array.map(novec, lambda(int i, string vret,
+							  string r, string fu,
+							  array(string) args) {
+						     return "    case "+i+": "+
+						       (vret?"res=":"")+
+						       fu+i+"v("+
+						       (args+({"zv4.v."+r}))*
+						       ","+"); break;";
+						   }, vret, rtypes, fu, args)*
+	"\n"+"\n  }\n";
+    else
+      res += "  switch(zv4.ty) {\n"+
+	Array.map(indices(rtypes),
+		  lambda(int i, string r, string fu, string vret,
+			 array(string) args, array(int) novec) {
+		    return "    case ZT_"+
+		    (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+
+		      ": switch(r234) {\n"+
+		      Array.map(novec, lambda(int i, string vret, string r,
+					      string fu, array(string) args) {
+					 return "      case "+i+": "+
+					   (vret?"res=":"")+
+					   fu+i+r+"v("+
+					   (args+({"zv4.v."+r}))*
+					   ","+"); break;";
+				       }, vret, r[i..i], fu, args)*
+		      "\n"+"\n    }\n    break;";
+		  }, rtypes, fu, vret, args, novec)*"\n"+
+	"\n  }\n";
+    break;
+  case 2:
+    if(sizeof(rtypes)==1)
+      res += (vret?"  res=":"  ")+fu+"("+
+	((args+(novec? Array.map(novec, lambda(int i, string rtypes) {
+					  return "zv4.v."+rtypes+"["+i+"]";
+					}, rtypes):({"zv4.v."+rtypes})))*",")+
+	");\n";
+    else
+      res += "  switch(zv4.ty) {\n"+
+	Array.map(indices(rtypes),
+		  lambda(int i, string r, string fu, string vret,
+			 array(string) args, array(int) novec) {
+		    return "    case ZT_"+
+		    (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+": "+
+		      (vret?"res=":"")+fu+r[i..i]+(novec?"(":"v(")+
+		      ((args+(novec? Array.map(novec, lambda(int i, string r) {
+							return "zv4.v."+r+
+							  "["+i+"]";
+						      }, r[i..i]):
+			      ({"zv4.v."+r[i..i]})))*",")+"); break;";
+		  }, rtypes, fu, vret, args, novec)*"\n"+
+	"\n  }\n";
+    break;
+  case 3:
+    if(sizeof(rtypes)==1)
+      res += "  if(r1n&ZT_ARRAY)\n"+
+	(vret?"    res=":"    ")+fu+"v("+(args+({"zv16."+rtypes}))*","+
+	");\n  else\n"+
+	(vret?"    res=":"    ")+fu+"("+(args+({"zv16."+rtypes+"[0]"}))*","+
+	");\n";
+    else
+      res += "  switch(r1n) {\n"+
+	Array.map(indices(rtypes),
+		  lambda(int i, string r, string fu, string vret,
+			 array(string) args, array(int) novec) {
+		    return "    case ZT_"+
+		    (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+": "+
+		      (vret?"res=":"")+fu+r[i..i]+"("+
+		      ((args+({"zv16."+r[i..i]+"[0]"}))*",")+"); break;\n"+
+		      "    case ZT_ARRAY|ZT_"+
+		    (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+": "+
+		      (vret?"res=":"")+fu+r[i..i]+"v("+
+		      ((args+({"zv16."+r[i..i]}))*",")+"); break;";
+		  }, rtypes, fu, vret, args, novec)*"\n"+
+	"\n  }\n";
+    break;
+  case -1:
+    res += "  switch(r1n) {\n"+
+      Array.map(indices(rtypes),
+		lambda(int i, string r, string fu, string vret,
+		       array(string) args, array(int) novec) {
+		  return "    case ZT_ARRAY|ZT_"+
+		  (['i':"INT",'f':"FLOAT",'d':"DOUBLE"])[r[i]]+": "+
+		    (vret?"res=":"")+fu+r[i..i]+"("+
+		    ((args+({"zv16."+r[i..i]}))*",")+"); break;";
+		}, rtypes, fu, vret, args, novec)*"\n"+
+      "\n  }\n";
+    break;
+  }
+
+  if(img_obj) {
+    res += "  release_img(&img);\n";
+  }
+  res += "  pop_n_elems(args);\n";
+  res += (vret? "  "+vret+"("+(vcast||"")+"res);\n":/*"  push_int(0);\n"*/"");
+  res += "}\n\n";
+  return ({res,prot});
+}
+
+string gen()
+{
+  string res = "";
+  array t = Array.transpose(func_misc);
+  array fn=t[0];
+  mapping ty = mkmapping(@t);
+  mapping prot = ([]);
+  foreach(indices(func_cat), string cat) {
+    fn += func_cat[cat];
+    ty |= mkmapping(func_cat[cat],
+		    rows(({cat}), allocate(sizeof(func_cat[cat]))));
+  }
+  sort(fn);
+  foreach(fn, string f) {
+    array(string) r = gen_func(f, ty[f]);
+    res += r[0];
+    prot[f]=r[1];
+  }
+  res += "void GL_add_auto_funcs()\n{\n";
+  res += "  pre_init();\n";
+  foreach(fn, string f)
+    res += "  add_function_constant(\""+f+"\", f_"+f+",\n\t\t\t\"function("+
+      prot[f]+")\", OPT_SIDE_EFFECT);\n";
+  foreach(sort(indices(constants)), string co)
+    res += "  add_integer_constant(\""+co+"\", "+constants[co]+", 0);\n";
+  res += "  post_init();\n";
+  res += "}\n";
+  return res;
+}
+
+void main(int argc, array(string) argv)
+{
+  array(string) f = Stdio.File("stdin")->read()/"@@";
+  write(({f[0],gen(),@f[1..]})*"");
+}
diff --git a/src/post_modules/GL/top.c b/src/post_modules/GL/top.c
new file mode 100644
index 0000000000000000000000000000000000000000..ae5e1c700ebf9a4181ab7c321375e29ac23f2718
--- /dev/null
+++ b/src/post_modules/GL/top.c
@@ -0,0 +1,388 @@
+/*
+ * $Id: top.c,v 1.11 1999/11/07 01:43:31 per fake $
+ *
+ */
+
+#include "config.h"
+
+#ifdef HAVE_GL
+
+#ifdef HAVE_WINDEF_H
+#include <windef.h>
+#endif /* HAVE_WINDEF_H */
+#ifdef HAVE_WINGDI_H
+#include <wingdi.h>
+#endif /* HAVE_WINGDI_H */
+#ifdef HAVE_GL_GL_H
+#include <GL/gl.h>
+#endif /* HAVE_GL_GL_H */
+#ifdef HAVE_GL_GLX_H
+#include <GL/glx.h>
+#endif /* HAVE_GL_GLX_H */
+
+#endif /* HAVE_GL */
+
+
+#include "global.h"
+
+RCSID("$Id: top.c,v 1.11 1999/11/07 01:43:31 per fake $");
+#include "stralloc.h"
+#include "pike_macros.h"
+#include "object.h"
+#include "program.h"
+#include "interpret.h"
+#include "builtin_functions.h"
+#include "module_support.h"
+#include "error.h"
+
+#ifdef HAVE_GL
+
+static void f_glGet(INT32 args)
+{
+  INT32 arg1;
+  GLint i, i2[4];
+  GLboolean b[4];
+  GLfloat f[16];
+
+  check_all_args("glGet", args, BIT_INT, 0);
+
+  arg1=sp[0-args].u.integer;
+
+  pop_n_elems(args);
+
+  switch(arg1) {
+  case GL_ACCUM_ALPHA_BITS:
+  case GL_ACCUM_BLUE_BITS:
+  case GL_ACCUM_GREEN_BITS:
+  case GL_ACCUM_RED_BITS:
+  case GL_ALPHA_BITS:
+  case GL_ALPHA_TEST_FUNC:
+  case GL_ATTRIB_STACK_DEPTH:
+  case GL_AUX_BUFFERS:
+  case GL_BLEND_DST:
+  case GL_BLEND_SRC:
+  case GL_BLUE_BITS:
+  case GL_CLIENT_ATTRIB_STACK_DEPTH:
+  case GL_COLOR_ARRAY_SIZE:
+  case GL_COLOR_ARRAY_STRIDE:
+  case GL_COLOR_ARRAY_TYPE:
+  case GL_COLOR_MATERIAL_FACE:
+  case GL_COLOR_MATERIAL_PARAMETER:
+  case GL_CULL_FACE_MODE:
+  case GL_DEPTH_BITS:
+  case GL_DEPTH_FUNC:
+  case GL_DRAW_BUFFER:
+  case GL_EDGE_FLAG_ARRAY_STRIDE:
+  case GL_FOG_HINT:
+  case GL_FOG_MODE:
+  case GL_FRONT_FACE:
+  case GL_GREEN_BITS:
+  case GL_INDEX_ARRAY_STRIDE:
+  case GL_INDEX_ARRAY_TYPE:
+  case GL_INDEX_BITS:
+  case GL_INDEX_OFFSET:
+  case GL_INDEX_SHIFT:
+  case GL_INDEX_WRITEMASK:
+  case GL_LINE_SMOOTH_HINT:
+  case GL_LINE_STIPPLE_PATTERN:
+  case GL_LINE_STIPPLE_REPEAT:
+  case GL_LIST_BASE:
+  case GL_LIST_INDEX:
+  case GL_LIST_MODE:
+  case GL_LOGIC_OP_MODE:
+  case GL_MAP1_GRID_SEGMENTS:
+  case GL_MATRIX_MODE:
+  case GL_MAX_CLIENT_ATTRIB_STACK_DEPTH:
+  case GL_MAX_ATTRIB_STACK_DEPTH:
+  case GL_MAX_CLIP_PLANES:
+  case GL_MAX_EVAL_ORDER:
+  case GL_MAX_LIGHTS:
+  case GL_MAX_LIST_NESTING:
+  case GL_MAX_MODELVIEW_STACK_DEPTH:
+  case GL_MAX_NAME_STACK_DEPTH:
+  case GL_MAX_PIXEL_MAP_TABLE:
+  case GL_MAX_PROJECTION_STACK_DEPTH:
+  case GL_MAX_TEXTURE_SIZE:
+  case GL_MAX_TEXTURE_STACK_DEPTH:
+  case GL_MODELVIEW_STACK_DEPTH:
+  case GL_NAME_STACK_DEPTH:
+  case GL_NORMAL_ARRAY_STRIDE:
+  case GL_NORMAL_ARRAY_TYPE:
+  case GL_PACK_ALIGNMENT:
+  case GL_PACK_ROW_LENGTH:
+  case GL_PACK_SKIP_PIXELS:
+  case GL_PACK_SKIP_ROWS:
+  case GL_PERSPECTIVE_CORRECTION_HINT:
+  case GL_PIXEL_MAP_A_TO_A_SIZE:
+  case GL_PIXEL_MAP_B_TO_B_SIZE:
+  case GL_PIXEL_MAP_G_TO_G_SIZE:
+  case GL_PIXEL_MAP_I_TO_A_SIZE:
+  case GL_PIXEL_MAP_I_TO_B_SIZE:
+  case GL_PIXEL_MAP_I_TO_G_SIZE:
+  case GL_PIXEL_MAP_I_TO_I_SIZE:
+  case GL_PIXEL_MAP_I_TO_R_SIZE:
+  case GL_PIXEL_MAP_R_TO_R_SIZE:
+  case GL_PIXEL_MAP_S_TO_S_SIZE:
+  case GL_POINT_SMOOTH_HINT:
+  case GL_POLYGON_MODE:
+  case GL_POLYGON_SMOOTH_HINT:
+  case GL_PROJECTION_STACK_DEPTH:
+  case GL_READ_BUFFER:
+  case GL_RED_BITS:
+  case GL_RENDER_MODE:
+  case GL_SHADE_MODEL:
+  case GL_STENCIL_BITS:
+  case GL_STENCIL_CLEAR_VALUE:
+  case GL_STENCIL_FAIL:
+  case GL_STENCIL_FUNC:
+  case GL_STENCIL_PASS_DEPTH_FAIL:
+  case GL_STENCIL_PASS_DEPTH_PASS:
+  case GL_STENCIL_REF:
+  case GL_STENCIL_VALUE_MASK:
+  case GL_STENCIL_WRITEMASK:
+  case GL_SUBPIXEL_BITS:
+  case GL_TEXTURE_BINDING_1D:
+  case GL_TEXTURE_BINDING_2D:
+  case GL_TEXTURE_COORD_ARRAY_SIZE:
+  case GL_TEXTURE_COORD_ARRAY_STRIDE:
+  case GL_TEXTURE_COORD_ARRAY_TYPE:
+  case GL_TEXTURE_STACK_DEPTH:
+  case GL_UNPACK_ALIGNMENT:
+  case GL_UNPACK_ROW_LENGTH:
+  case GL_UNPACK_SKIP_PIXELS:
+  case GL_UNPACK_SKIP_ROWS:
+  case GL_VERTEX_ARRAY_SIZE:
+  case GL_VERTEX_ARRAY_STRIDE:
+  case GL_VERTEX_ARRAY_TYPE:
+    glGetIntegerv(arg1, &i);
+    push_int(i);
+    break;
+
+  case GL_MAP2_GRID_SEGMENTS:
+  case GL_MAX_VIEWPORT_DIMS:
+    glGetIntegerv(arg1, i2);
+    push_int(i2[0]);
+    push_int(i2[1]);
+    f_aggregate(2);
+    break;
+
+  case GL_SCISSOR_BOX:
+  case GL_VIEWPORT:
+    glGetIntegerv(arg1, i2);
+    push_int(i2[0]);
+    push_int(i2[1]);
+    push_int(i2[2]);
+    push_int(i2[3]);
+    f_aggregate(4);
+    break;
+
+  case GL_ALPHA_TEST:
+  case GL_AUTO_NORMAL:
+  case GL_BLEND:
+  case GL_CLIP_PLANE0:
+  case GL_CLIP_PLANE1:
+  case GL_CLIP_PLANE2:
+  case GL_CLIP_PLANE3:
+  case GL_CLIP_PLANE4:
+  case GL_CLIP_PLANE5:
+  case GL_COLOR_ARRAY:
+  case GL_COLOR_LOGIC_OP:
+  case GL_COLOR_MATERIAL:
+  case GL_CULL_FACE:
+  case GL_CURRENT_RASTER_POSITION_VALID:
+  case GL_DEPTH_TEST:
+  case GL_DEPTH_WRITEMASK:
+  case GL_DITHER:
+  case GL_DOUBLEBUFFER:
+  case GL_EDGE_FLAG:
+  case GL_EDGE_FLAG_ARRAY:
+  case GL_FOG:
+  case GL_INDEX_ARRAY:
+  case GL_INDEX_LOGIC_OP:
+  case GL_INDEX_MODE:
+  case GL_LIGHT0:
+  case GL_LIGHT1:
+  case GL_LIGHT2:
+  case GL_LIGHT3:
+  case GL_LIGHT4:
+  case GL_LIGHT5:
+  case GL_LIGHT6:
+  case GL_LIGHT7:
+  case GL_LIGHTING:
+  case GL_LIGHT_MODEL_LOCAL_VIEWER:
+  case GL_LIGHT_MODEL_TWO_SIDE:
+  case GL_LINE_SMOOTH:
+  case GL_LINE_STIPPLE:
+  case GL_MAP1_COLOR_4:
+  case GL_MAP1_INDEX:
+  case GL_MAP1_NORMAL:
+  case GL_MAP1_TEXTURE_COORD_1:
+  case GL_MAP1_TEXTURE_COORD_2:
+  case GL_MAP1_TEXTURE_COORD_3:
+  case GL_MAP1_TEXTURE_COORD_4:
+  case GL_MAP1_VERTEX_3:
+  case GL_MAP1_VERTEX_4:
+  case GL_MAP2_COLOR_4:
+  case GL_MAP2_INDEX:
+  case GL_MAP2_NORMAL:
+  case GL_MAP2_TEXTURE_COORD_1:
+  case GL_MAP2_TEXTURE_COORD_2:
+  case GL_MAP2_TEXTURE_COORD_3:
+  case GL_MAP2_TEXTURE_COORD_4:
+  case GL_MAP2_VERTEX_3:
+  case GL_MAP2_VERTEX_4:
+  case GL_MAP_COLOR:
+  case GL_MAP_STENCIL:
+  case GL_NORMAL_ARRAY:
+  case GL_NORMALIZE:
+  case GL_PACK_LSB_FIRST:
+  case GL_PACK_SWAP_BYTES:
+  case GL_POINT_SMOOTH:
+  case GL_POLYGON_OFFSET_FILL:
+  case GL_POLYGON_OFFSET_LINE:
+  case GL_POLYGON_OFFSET_POINT:
+  case GL_POLYGON_SMOOTH:
+  case GL_POLYGON_STIPPLE:
+  case GL_RGBA_MODE:
+  case GL_SCISSOR_TEST:
+  case GL_STENCIL_TEST:
+  case GL_STEREO:
+  case GL_TEXTURE_1D:
+  case GL_TEXTURE_2D:
+  case GL_TEXTURE_COORD_ARRAY:
+  case GL_TEXTURE_GEN_Q:
+  case GL_TEXTURE_GEN_R:
+  case GL_TEXTURE_GEN_S:
+  case GL_TEXTURE_GEN_T:
+  case GL_UNPACK_LSB_FIRST:
+  case GL_UNPACK_SWAP_BYTES:
+  case GL_VERTEX_ARRAY:
+    glGetBooleanv(arg1, b);
+    push_int(b[0]);
+    break;
+
+  case GL_ALPHA_BIAS:
+  case GL_ALPHA_SCALE:
+  case GL_ALPHA_TEST_REF:
+  case GL_BLUE_BIAS:
+  case GL_BLUE_SCALE:
+  case GL_CURRENT_INDEX:
+  case GL_CURRENT_RASTER_DISTANCE:
+  case GL_CURRENT_RASTER_INDEX:
+  case GL_DEPTH_BIAS:
+  case GL_DEPTH_CLEAR_VALUE:
+  case GL_DEPTH_SCALE:
+  case GL_FOG_DENSITY:
+  case GL_FOG_END:
+  case GL_FOG_INDEX:
+  case GL_FOG_START:
+  case GL_GREEN_BIAS:
+  case GL_GREEN_SCALE:
+  case GL_INDEX_CLEAR_VALUE:
+  case GL_LINE_WIDTH:
+  case GL_LINE_WIDTH_GRANULARITY:
+  case GL_POINT_SIZE:
+  case GL_POINT_SIZE_GRANULARITY:
+  case GL_POLYGON_OFFSET_FACTOR:
+  case GL_POLYGON_OFFSET_UNITS:
+  case GL_RED_BIAS:
+  case GL_RED_SCALE:
+  case GL_ZOOM_X:
+  case GL_ZOOM_Y:
+    glGetFloatv(arg1, f);
+    push_float(f[0]);
+    break;
+
+  case GL_DEPTH_RANGE:
+  case GL_LINE_WIDTH_RANGE:
+  case GL_MAP1_GRID_DOMAIN:
+  case GL_POINT_SIZE_RANGE:
+    glGetFloatv(arg1, f);
+    push_float(f[0]);
+    push_float(f[1]);
+    f_aggregate(2);
+    break;
+
+  case GL_CURRENT_NORMAL:
+    glGetFloatv(arg1, f);
+    push_float(f[0]);
+    push_float(f[1]);
+    push_float(f[2]);
+    f_aggregate(3);
+    break;
+
+  case GL_ACCUM_CLEAR_VALUE:
+  case GL_COLOR_CLEAR_VALUE:
+  case GL_CURRENT_COLOR:
+  case GL_CURRENT_RASTER_COLOR:
+  case GL_CURRENT_RASTER_POSITION:
+  case GL_CURRENT_RASTER_TEXTURE_COORDS:
+  case GL_CURRENT_TEXTURE_COORDS:
+  case GL_FOG_COLOR:
+  case GL_LIGHT_MODEL_AMBIENT:
+  case GL_MAP2_GRID_DOMAIN:
+    glGetFloatv(arg1, f);
+    push_float(f[0]);
+    push_float(f[1]);
+    push_float(f[2]);
+    push_float(f[3]);
+    f_aggregate(4);
+    break;
+
+  case GL_COLOR_WRITEMASK:
+    glGetBooleanv(arg1, b);
+    push_int(b[0]);
+    push_int(b[1]);
+    push_int(b[2]);
+    push_int(b[3]);
+    f_aggregate(4);
+    break;
+
+  case GL_MODELVIEW_MATRIX:
+  case GL_PROJECTION_MATRIX:
+  case GL_TEXTURE_MATRIX:
+    glGetFloatv(arg1, f);
+    push_float(f[0]);
+    push_float(f[1]);
+    push_float(f[2]);
+    push_float(f[3]);
+    push_float(f[4]);
+    push_float(f[5]);
+    push_float(f[6]);
+    push_float(f[7]);
+    push_float(f[8]);
+    push_float(f[9]);
+    push_float(f[10]);
+    push_float(f[11]);
+    push_float(f[12]);
+    push_float(f[13]);
+    push_float(f[14]);
+    push_float(f[15]);
+    f_aggregate(16);
+    break;
+
+  default:
+    error("glGet: Unsupported parameter name\n");
+  }
+}
+
+#endif /* HAVE_GL */
+
+
+void pike_module_init( void )
+{
+#ifdef HAVE_GL
+  extern void GL_add_auto_funcs(void);
+
+  add_function_constant("glGet", f_glGet,
+			"function(int:int|float|array(int)|array(float))",
+			OPT_SIDE_EFFECT);
+  GL_add_auto_funcs();
+#endif /* HAVE_GL */
+}
+
+
+void pike_module_exit( void )
+{
+}
+
diff --git a/src/post_modules/GTK/.cvsignore b/src/post_modules/GTK/.cvsignore
new file mode 100755
index 0000000000000000000000000000000000000000..21a50d44190619ccd803d89966b1735f31be4ab7
--- /dev/null
+++ b/src/post_modules/GTK/.cvsignore
@@ -0,0 +1,11 @@
+*.c
+configure
+docs
+config.h.in
+ChangeLog
+Makefile
+config.status
+config.cache
+config.h
+config.log
+aclocal.m4
diff --git a/src/post_modules/GTK/.gitignore b/src/post_modules/GTK/.gitignore
new file mode 100755
index 0000000000000000000000000000000000000000..3b7c5ebd440af13718fb39b23899bb8d4c31a34e
--- /dev/null
+++ b/src/post_modules/GTK/.gitignore
@@ -0,0 +1,11 @@
+/*.c
+/configure
+/docs
+/config.h.in
+/ChangeLog
+/Makefile
+/config.status
+/config.cache
+/config.h
+/config.log
+/aclocal.m4
diff --git a/src/post_modules/GTK/AUTHORS b/src/post_modules/GTK/AUTHORS
new file mode 100644
index 0000000000000000000000000000000000000000..6772f6bbd6f9ea9cb20cc8341363780a617d3c63
--- /dev/null
+++ b/src/post_modules/GTK/AUTHORS
@@ -0,0 +1,6 @@
+PiGTK is written by Per Hedbor <per@idonex.se>
+
+The following people have contributed:
+Fredrik H�binette 	<hubbe@hubbe.net>
+David Hedbor		<david@hedbor.org>
+Peter bortas		<peter@idonex.se>
\ No newline at end of file
diff --git a/src/post_modules/GTK/Makefile.in b/src/post_modules/GTK/Makefile.in
new file mode 100644
index 0000000000000000000000000000000000000000..f1c43adf0318ba9081a5856605c0e590d27af669
--- /dev/null
+++ b/src/post_modules/GTK/Makefile.in
@@ -0,0 +1,42 @@
+# This line is needed on some machines.
+SRCDIR=@srcdir@
+VPATH=@srcdir@:@srcdir@/../..:../..:.
+MODNAME=GTK
+DEST=@prefix@/lib/pike/modules/
+OBJS=dummy.o
+MODULE_LDFLAGS=@LDFLAGS@ @LIBS@ @PGTK_LIBS@
+MODULE_CFLAGS=@PGTK_CFLAGS@
+CONFIG_HEADERS=config.h
+
+
+# OK.. This is somewhat confusing
+# 
+# WITH_GTK == 1
+#   override -> sources1 -> [SET OBJS] -> all
+#
+# WITH_GTK == 0
+#   override -> sources0 -> all
+#
+
+override:  sources@WITH_GTK@
+	@:
+
+@dynamic_module_makefile@
+
+sources1:
+	$(RUNPIKE) $(SRCDIR)/make_sources.pike $(SRCDIR)/source
+	$(RUNPIKE) $(SRCDIR)/build_pgtk.pike $(SRCDIR)
+	$(MAKE) $(MAKE_FLAGS) "OBJS=`cat files_to_compile`" all
+
+sources0:
+	echo Pike-GTK disabled.
+	$(MAKE) $(MAKE_FLAGS) all
+
+quick_docs:
+	-$(RUNPIKE) $(SRCDIR)/dump_cursors.pike docs/cursor_
+	$(RUNPIKE) $(SRCDIR)/build_pgtk.pike $(SRCDIR) docs
+
+docs: install
+	$(MAKE) quick_docs
+
+
diff --git a/src/post_modules/GTK/aclocal.m4 b/src/post_modules/GTK/aclocal.m4
new file mode 100644
index 0000000000000000000000000000000000000000..12d95b00bc64fb7ff51f46f690957992f93aeca8
--- /dev/null
+++ b/src/post_modules/GTK/aclocal.m4
@@ -0,0 +1,326 @@
+pushdef([AC_PROG_CC_WORKS],
+[
+  popdef([AC_PROG_CC_WORKS])
+  if test "${ac_prog_cc_works_this_run-}" != "yes" ; then
+    AC_PROG_CC_WORKS
+    ac_prog_cc_works_this_run="${ac_cv_prog_cc_works-no}"
+    export ac_prog_cc_works_this_run
+  else
+    AC_MSG_CHECKING([whether the C compiler ($CC $CFLAGS $LDFLAGS) works])
+    AC_MSG_RESULT([(cached) yes])
+  fi
+])
+
+pushdef([AC_PROG_CC],
+[
+  popdef([AC_PROG_CC])
+
+  AC_PROG_CC
+
+  case "`$CC -V 2>&1|head -1`" in
+    tcc*)
+      TCC="yes"
+      if echo "$CC $CFLAGS $CPPFLAGS" | grep " -Y" >/dev/null; then :; else
+	# We want to use the system API's...
+	CPPFLAGS="-Ysystem $CPPFLAGS"
+      fi
+    ;;
+    *) TCC="no" ;;
+  esac
+])
+
+define([MY_AC_PROG_CC],
+[
+define(ac_cv_prog_CC,pike_cv_prog_CC)
+AC_PROG_CC
+undefine([ac_cv_prog_CC])
+])
+
+pushdef([AC_CONFIG_HEADER],
+[
+  CONFIG_HEADERS="$1"
+  popdef([AC_CONFIG_HEADER])
+  AC_CONFIG_HEADER($1)
+])
+
+AC_DEFUN(AC_MY_CHECK_TYPE,
+[
+AC_MSG_CHECKING([for $1])
+AC_CACHE_VAL(ac_cv_type_$1,
+[
+AC_TRY_COMPILE([
+#include <sys/types.h>
+
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+
+],[
+$1 tmp;
+],ac_cv_type_$1=yes,ac_cv_type_$1=no)
+])
+
+if test $ac_cv_type_$1 = no; then
+  AC_DEFINE($1,$2)
+  AC_MSG_RESULT(no)
+else
+  AC_MSG_RESULT(yes)
+fi
+])
+
+
+AC_DEFUN(AC_TRY_ASSEMBLE,
+[ac_c_ext=$ac_ext
+ ac_ext=${ac_s_ext-s}
+ cat > conftest.$ac_ext <<EOF
+	.file "configure"
+[$1]
+EOF
+if AC_TRY_EVAL(ac_compile); then
+  ac_ext=$ac_c_ext
+  ifelse([$2], , :, [  $2
+  rm -rf conftest*])
+else
+  echo "configure: failed program was:" >&AC_FD_CC
+  cat conftest.$ac_ext >&AC_FD_CC
+  ac_ext=$ac_c_ext
+ifelse([$3], , , [  rm -rf conftest*
+  $3
+])dnl
+fi
+rm -rf conftest*])
+
+
+define([AC_LOW_MODULE_INIT],
+[
+# $Id: aclocal.m4,v 1.1 1999/11/07 01:38:48 per Exp $
+
+MY_AC_PROG_CC
+
+AC_DEFINE(POSIX_SOURCE)
+
+AC_SUBST(CONFIG_HEADERS)
+
+AC_SUBST_FILE(dependencies)
+dependencies=$srcdir/dependencies
+
+AC_SUBST_FILE(dynamic_module_makefile)
+AC_SUBST_FILE(static_module_makefile)
+])
+
+
+define([AC_MODULE_INIT],
+[
+AC_LOW_MODULE_INIT()
+
+ifdef([PIKE_INCLUDE_PATH],
+[
+dynamic_module_makefile=PIKE_INCLUDE_PATH/dynamic_module_makefile
+static_module_makefile=PIKE_INCLUDE_PATH/dynamic_module_makefile
+],[
+dynamic_module_makefile=../dynamic_module_makefile
+static_module_makefile=../static_module_makefile
+
+counter=.
+
+while test ! -f "$dynamic_module_makefile"
+do
+  counter=.$counter
+  if test $counter = .......... ; then
+    exit 1
+  else
+    :
+  fi
+  dynamic_module_makefile=../$dynamic_module_makefile
+  static_module_makefile=../$static_module_makefile
+done
+])
+])
+
+dnl aclocal.m4 generated automatically by aclocal 1.3
+
+dnl Copyright (C) 1994, 1995, 1996, 1997, 1998 Free Software Foundation, Inc.
+dnl This Makefile.in is free software; the Free Software Foundation
+dnl gives unlimited permission to copy and/or distribute it,
+dnl with or without modifications, as long as this notice is preserved.
+
+dnl This program is distributed in the hope that it will be useful,
+dnl but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+dnl even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+dnl PARTICULAR PURPOSE.
+
+dnl Configure paths for GTK+
+dnl Owen Taylor     97-11-3
+
+dnl AM_PATH_GTK([MINIMUM-VERSION, [ACTION-IF-FOUND [, ACTION-IF-NOT-FOUND]]])
+dnl Test for GTK, and define GTK_CFLAGS and GTK_LIBS
+dnl
+AC_DEFUN(AM_PATH_GTK,
+[dnl 
+dnl Get the cflags and libraries from the gtk-config script
+dnl
+AC_ARG_WITH(gtk-prefix,[  --with-gtk-prefix=PFX   Prefix where GTK is installed (optional)],
+            gtk_config_prefix="$withval", gtk_config_prefix="")
+AC_ARG_WITH(gtk-exec-prefix,[  --with-gtk-exec-prefix=PFX Exec prefix where GTK is installed (optional)],
+            gtk_config_exec_prefix="$withval", gtk_config_exec_prefix="")
+AC_ARG_ENABLE(gtktest, [  --disable-gtktest       Do not try to compile and run a test GTK program],
+		    , enable_gtktest=yes)
+
+  if test x$gtk_config_exec_prefix != x ; then
+     gtk_config_args="$gtk_config_args --exec-prefix=$gtk_config_exec_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_exec_prefix/bin/gtk-config
+     fi
+  fi
+  if test x$gtk_config_prefix != x ; then
+     gtk_config_args="$gtk_config_args --prefix=$gtk_config_prefix"
+     if test x${GTK_CONFIG+set} != xset ; then
+        GTK_CONFIG=$gtk_config_prefix/bin/gtk-config
+     fi
+  fi
+
+  AC_PATH_PROG(GTK_CONFIG, gtk-config, no)
+  min_gtk_version=ifelse([$1], ,0.99.7,$1)
+  AC_MSG_CHECKING(for GTK - version >= $min_gtk_version)
+  no_gtk=""
+  if test "$GTK_CONFIG" = "no" ; then
+    no_gtk=yes
+  else
+    GTK_CFLAGS=`$GTK_CONFIG $gtk_config_args --cflags`
+    GTK_LIBS=`$GTK_CONFIG $gtk_config_args --libs`
+    gtk_config_major_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\1/'`
+    gtk_config_minor_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\2/'`
+    gtk_config_micro_version=`$GTK_CONFIG $gtk_config_args --version | \
+           sed 's/\([[0-9]]*\).\([[0-9]]*\).\([[0-9]]*\)/\3/'`
+    if test "x$enable_gtktest" = "xyes" ; then
+      ac_save_CFLAGS="$CFLAGS"
+      ac_save_LIBS="$LIBS"
+      CFLAGS="$CFLAGS $GTK_CFLAGS"
+      LIBS="$LIBS $GTK_LIBS"
+dnl
+dnl Now check if the installed GTK is sufficiently new. (Also sanity
+dnl checks the results of gtk-config to some extent
+dnl
+      rm -f conf.gtktest
+      AC_TRY_RUN([
+#include <gtk/gtk.h>
+#include <stdio.h>
+
+int 
+main ()
+{
+  int major, minor, micro;
+  char *tmp_version;
+
+  system ("touch conf.gtktest");
+
+  /* HP/UX 9 (%@#!) writes to sscanf strings */
+  tmp_version = g_strdup("$min_gtk_version");
+  if (sscanf(tmp_version, "%d.%d.%d", &major, &minor, &micro) != 3) {
+     printf("%s, bad version string\n", "$min_gtk_version");
+     exit(1);
+   }
+
+  if ((gtk_major_version != $gtk_config_major_version) ||
+      (gtk_minor_version != $gtk_config_minor_version) ||
+      (gtk_micro_version != $gtk_config_micro_version))
+    {
+      printf("\n*** 'gtk-config --version' returned %d.%d.%d, but GTK+ (%d.%d.%d)\n", 
+             $gtk_config_major_version, $gtk_config_minor_version, $gtk_config_micro_version,
+             gtk_major_version, gtk_minor_version, gtk_micro_version);
+      printf ("*** was found! If gtk-config was correct, then it is best\n");
+      printf ("*** to remove the old version of GTK+. You may also be able to fix the error\n");
+      printf("*** by modifying your LD_LIBRARY_PATH enviroment variable, or by editing\n");
+      printf("*** /etc/ld.so.conf. Make sure you have run ldconfig if that is\n");
+      printf("*** required on your system.\n");
+      printf("*** If gtk-config was wrong, set the environment variable GTK_CONFIG\n");
+      printf("*** to point to the correct copy of gtk-config, and remove the file config.cache\n");
+      printf("*** before re-running configure\n");
+    } 
+  else
+    {
+      if ((gtk_major_version > major) ||
+        ((gtk_major_version == major) && (gtk_minor_version > minor)) ||
+        ((gtk_major_version == major) && (gtk_minor_version == minor) && (gtk_micro_version >= micro)))
+      {
+        return 0;
+       }
+     else
+      {
+        printf("\n*** An old version of GTK+ (%d.%d.%d) was found.\n",
+               gtk_major_version, gtk_minor_version, gtk_micro_version);
+        printf("*** You need a version of GTK+ newer than %d.%d.%d. The latest version of\n",
+	       major, minor, micro);
+        printf("*** GTK+ is always available from ftp://ftp.gtk.org.\n");
+        printf("***\n");
+        printf("*** If you have already installed a sufficiently new version, this error\n");
+        printf("*** probably means that the wrong copy of the gtk-config shell script is\n");
+        printf("*** being found. The easiest way to fix this is to remove the old version\n");
+        printf("*** of GTK+, but you can also set the GTK_CONFIG environment to point to the\n");
+        printf("*** correct copy of gtk-config. (In this case, you will have to\n");
+        printf("*** modify your LD_LIBRARY_PATH enviroment variable, or edit /etc/ld.so.conf\n");
+        printf("*** so that the correct libraries are found at run-time))\n");
+      }
+    }
+  return 1;
+}
+],, no_gtk=yes,[echo $ac_n "cross compiling; assumed OK... $ac_c"])
+       CFLAGS="$ac_save_CFLAGS"
+       LIBS="$ac_save_LIBS"
+     fi
+  fi
+  if test "x$no_gtk" = x ; then
+     AC_MSG_RESULT(yes)
+     ifelse([$2], , :, [$2])     
+  else
+     AC_MSG_RESULT(no)
+     if test "$GTK_CONFIG" = "no" ; then
+       echo "*** The gtk-config script installed by GTK could not be found"
+       echo "*** If GTK was installed in PREFIX, make sure PREFIX/bin is in"
+       echo "*** your path, or set the GTK_CONFIG environment variable to the"
+       echo "*** full path to gtk-config."
+     else
+       if test -f conf.gtktest ; then
+        :
+       else
+          echo "*** Could not run GTK test program, checking why..."
+          CFLAGS="$CFLAGS $GTK_CFLAGS"
+          LIBS="$LIBS $GTK_LIBS"
+          AC_TRY_LINK([
+#include <gtk/gtk.h>
+#include <stdio.h>
+],      [ return ((gtk_major_version) || (gtk_minor_version) || (gtk_micro_version)); ],
+        [ echo "*** The test program compiled, but did not run. This usually means"
+          echo "*** that the run-time linker is not finding GTK or finding the wrong"
+          echo "*** version of GTK. If it is not finding GTK, you'll need to set your"
+          echo "*** LD_LIBRARY_PATH environment variable, or edit /etc/ld.so.conf to point"
+          echo "*** to the installed location  Also, make sure you have run ldconfig if that"
+          echo "*** is required on your system"
+	  echo "***"
+          echo "*** If you have an old version installed, it is best to remove it, although"
+          echo "*** you may also be able to get things to work by modifying LD_LIBRARY_PATH"
+          echo "***"
+          echo "*** If you have a RedHat 5.0 system, you should remove the GTK package that"
+          echo "*** came with the system with the command"
+          echo "***"
+          echo "***    rpm --erase --nodeps gtk gtk-devel" ],
+        [ echo "*** The test program failed to compile or link. See the file config.log for the"
+          echo "*** exact error that occured. This usually means GTK was incorrectly installed"
+          echo "*** or that you have moved GTK since it was installed. In the latter case, you"
+          echo "*** may want to edit the gtk-config script: $GTK_CONFIG" ])
+          CFLAGS="$ac_save_CFLAGS"
+          LIBS="$ac_save_LIBS"
+       fi
+     fi
+     GTK_CFLAGS=""
+     GTK_LIBS=""
+     ifelse([$3], , :, [$3])
+  fi
+  AC_SUBST(GTK_CFLAGS)
+  AC_SUBST(GTK_LIBS)
+  rm -f conf.gtktest
+])
+
diff --git a/src/post_modules/GTK/build_pgtk.pike b/src/post_modules/GTK/build_pgtk.pike
new file mode 100755
index 0000000000000000000000000000000000000000..e7742b407866383e1946a09c3eda5a0f3eeb7912
--- /dev/null
+++ b/src/post_modules/GTK/build_pgtk.pike
@@ -0,0 +1,1394 @@
+int ln, eml=-100;
+string buffer="";
+
+mapping warn = 
+([
+  "nodocs":1,
+  "noargs":1,
+  "noexample":1,
+  "cstyle":1,
+]);
+
+mapping struct = ([ "global":([]) ]);
+mapping signals = ([  ]);
+string glob_prototypes="";
+string line_id = "";
+
+int last_ended_with_nl, debug_mode=1, no_hashline;
+void emit_nl(string what)
+{
+  if(!no_hashline && debug_mode)
+  {
+    buffer += (last_ended_with_nl?line_id:"")
+      + (what/"\n") * ("\n"+line_id) + "\n";
+    last_ended_with_nl = 1;
+  } else
+    buffer += what;
+}
+
+string classname( string what )
+{
+  if(what[0] == 'p' && upper_case(what[1..1])==what[1..1])
+    return "GTK."+what;
+  string base = "GTK.";
+  sscanf(what, "%s.", what);
+  if(sscanf(what, "Gdk_%s", what) ||
+     sscanf(what, "Gdk%s", what))
+    base = "GDK.";
+  if(what == "Atom")
+    return "GDK._Atom";
+  return base+sillycaps( what, 1 );
+}
+
+string sillycaps( string what, int|void nolower )
+{
+  string a;
+  if(what[0]=='_') return what;
+  if(!nolower) 
+    what = lower_case(what);
+  what = String.capitalize(what);
+  while(sscanf(what, "%s_%s", a, what) == 2)
+    what = a+String.capitalize(what);
+  if(nolower) return what;
+  return "Gtk"+what;
+}
+
+void emit_proto(string what)
+{
+  emit(what);
+  glob_prototypes += replace(what,"\n", ";\n");
+}
+
+string files="", head;
+string internal_progname = "globals";
+void end_last_program()
+{ 
+  eml=-1;
+  files += "pgtk_"+internal_progname+".c ";
+  if(do_docs) return;
+//   werror(internal_progname+"...\n");
+  string data;  
+//   if(Stdio.file_size("pgtk_"+internal_progname+".c") !=
+//      (strlen(buffer)+strlen(head)))
+//   {
+  if(Stdio.read_bytes( "pgtk_"+internal_progname+".c" ) !=
+     head+buffer )
+  {
+    werror("Creating pgtk_"+internal_progname+".c\n");
+    object outf = Stdio.File("pgtk_"+internal_progname+".c", "rwct"); 
+    outf->write(head);
+    outf->write(buffer);
+  }
+//     werror("Not modified: pgtk_"+internal_progname+".c\n");
+//   }
+  buffer="";
+}
+
+void begin_new_program(string which)
+{
+  internal_progname = which;
+}
+
+int current_expected_line, current_line;
+string emit_line_id;
+void emit(string what)
+{
+  if(!no_hashline && debug_mode)
+  {
+    if( what[0..4] == "#line" )
+    {
+      line_id = what;
+      if((int)what[5..] != current_line)
+        emit_line_id = what;
+      else
+        emit_line_id = "";
+      current_line = current_expected_line = (int)what[5..];
+    }
+    else if(last_ended_with_nl)
+    {
+      if(current_line++ == current_expected_line)
+      {
+        if(sizeof(replace(what, ({" ","\t", "\r", "\n" }),
+                          ({"","","",""}))))
+          buffer += emit_line_id+what;
+        else
+          buffer += what;
+      }
+      else
+        buffer += line_id+what;
+    }
+    else
+      buffer += what;
+    if(strlen(what))
+      last_ended_with_nl = what[-1] == '\n';
+  } else
+    buffer += what;
+}
+
+int _num_functions;
+void emit_program_block(mapping block, string cl)
+{
+  line_id = "";
+  foreach(sort(indices(block)), string f)
+  {
+    _num_functions++;
+    if( search( block[f], "()" ) != -1 ||
+         search( block[f], "(:" ) != -1 ||
+        search( block[f], ":)" ) != -1 ||
+        search( block[f], " " ) != -1 ||
+        sizeof(block[f]/")") != sizeof( block[f] / "(" ) ||
+        ((sizeof(block[f]/")") != sizeof( block[f] / ":" )+
+          sizeof(block[f]/"array")-1) &&
+         (sizeof(block[f]/")") != sizeof( block[f] / ":" )) ) ||
+        search( block[f], "function" ) == -1)
+    {
+        werror(lines[cl+f]+": Warning: suspicious type "+block[f]+"\n");
+    }      
+    switch(f)
+    {
+     case "union":
+       emit_nl("   add_function(\"`|\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       emit_nl("   add_function(\"`+\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       break;
+     case "intersection":
+       emit_nl("   add_function(\"`&\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       break;
+     case "subtract":
+       emit_nl("   add_function(\"`-\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       break;
+     case "equal":
+       emit_nl("   add_function(\"`==\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       break;
+     case "lt":
+       emit_nl("   add_function(\"`<\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       break;
+     case "xor":
+       emit_nl("   add_function(\"`^\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       break;
+     case "not":
+       emit_nl("   add_function(\"`~\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       break;
+     case "gt":
+       emit_nl("   add_function(\"`>\", pgtk_"+cl+"_"+f+",\n"
+               "               "+block[f]+", 0);\n");
+    _num_functions++;
+       break;
+    }
+    emit_nl("   add_function(\""+f+"\", pgtk_"+cl+"_"+f+",\n"
+	    "               "+block[f]+", 0);\n");
+  }
+}
+
+mapping docs = ([]), true_types = ([]), named = ([]);
+mapping lines = ([]), examples = ([]);
+
+void print_inherited_functions( string cl, object fd )
+{
+  foreach(sort(indices(struct[cl]))-({"inherit"}), string fun)
+  {
+    string a,b;
+    string a = true_types[cl+fun][1],b=true_types[cl+fun][0];
+    if( (a-" ") == "void"  )
+      a = "";
+//     sscanf(struct[cl][fun], "\"function(%s:%s)\"", a, b);
+    fd->write("<dt><b>"+b+" <a href="+cl+".html#"+fun+">"+
+	      classname(cl)+"."+fun+"</a>"
+	      "( "+replace(a, ",", ", ")+" );</b>\n");
+  }
+
+  if(struct[cl]["inherit"])
+    print_inherited_functions( struct[cl]["inherit"], fd );
+
+}
+
+void print_signals( mapping sigs, object on, string|void p)
+{
+  if(!sigs) return;
+  if(p) 
+    p = sillycaps(p,1)+".";
+  else 
+    p="";
+  foreach(sort(indices(sigs)), string s)
+    on->write("<dt><b>GTK.s_"+s+"</b><dd>"+sigs[s]+"\n");
+}
+
+void print_inherited_signals( string cl, object fd )
+{
+  print_signals( signals[cl], fd, cl );
+  if(struct[cl]["inherit"])
+    print_inherited_signals( struct[cl]["inherit"], fd );
+}
+
+void print_function_defs( string f, int|void global )
+{
+  rm("docs/"+f+".html");
+  if(f == "global")
+    global = 1;
+//   if(global)
+//     werror("global functions\n");
+  object fd = Stdio.File("docs/"+f+".html", "wct");
+
+//   fd->write("<body bgcolor=white text=black><a href=\"\">Index</a><p>\n");
+
+
+
+  if(global)
+    fd->write("<h1>Global Pike GTK functions</h1><p>\n");
+  else if( struct[f]->create )
+  {
+    if( warn->noexample )
+      if( !examples[ lower_case(f) ]  )
+        werror(lines[f]+": Warning: No example image\n");
+    fd->write("<h1>"+classname(f)+"</h1>\n");
+  } else {
+    fd->write("<h1>"+classname(f)+" (abstract class)</h1>\n");
+  }
+  fd->write("<blockquote>"+(docs[f]?docs[f]:"")+"</blockquote>\n");
+
+  if(!global)
+  {
+    if(struct[f]["inherit"])
+      fd->write("Inherits <a href="+struct[f]["inherit"]+".html>"+
+                classname( struct[f]["inherit"] )+"</a><p>");
+
+    foreach(sort(indices(struct)), string w)
+      if(struct[w]["inherit"] == f)
+        fd->write("Inherited by <a href="+w+".html>"+classname(w)+"</a><br>");
+  }
+  fd->write("<p>");
+
+  if(sizeof(indices(struct[f])) > 1)
+  {
+    if(struct[f]->create)
+    {
+      string a = true_types[f+"create"][1];
+      if( (a-" ") == "void"  )
+        a = "";
+      if( warn->noargs )
+        if(strlen(a) && !named[ f + "create" ] )
+          werror(lines[ f + "create" ]+": Warning: Arguments not named\n");
+
+//       sscanf(struct[f]->create, "\"function(%s:%s)\"", a, b);
+      fd->write("<h2>Constructor</h2>\n");
+      fd->write("<dl>");
+      fd->write("<dt><b>"+
+                (global?"GTK":(classname(f)+" "+classname(f)))
+                +"( "+replace(a, ",", ", ")+" );</b>\n");
+      if( warn->nodocs )
+        if(!docs[f+"create"])
+          werror(lines[ f + "create" ]+
+                 ": Warning: No documentation for constructor\n");
+
+      fd->write("<dd>"+(docs[f+"create"]?docs[f+"create"]:"")+"\n");
+      fd->write("</dl>");
+    }
+    if(!global)
+      fd->write("<h2>Methods</h2>\n");
+    fd->write("<dl>");
+    foreach(sort(indices(struct[f])), string fun)
+    {
+      if(fun != "inherit")
+      {
+	string a = true_types[f+fun][1],b=true_types[f+fun][0];
+        if( (a-" ") == "void"  )
+          a = "";
+// 	sscanf(struct[f][fun], "\"function(%s:%s)\"", a, b);
+	if(fun == "create" || fun == "destroy")
+	  ;
+	else
+	{
+          if( warn->noargs )
+            if(strlen(a) && !named[ f + fun ] )
+              werror(lines[f+fun]+": Warning: Arguments not named\n");
+	  fd->write("<a name=\""+fun+"\"><dt><b>"+b+" "+(global?"GTK.":"")
+                    +fun+"( "+replace(a, ",", ", ")+" );</b>\n");
+          if(!docs[f+fun] || !strlen(docs[f+fun]))
+          {
+            if( warn->nodocs )
+              werror(lines[ f + fun ]+
+                     ": Warning: No documentation for "+fun+"\n");
+          }
+          else
+          {
+            if( warn->cstyle )
+            {
+              if( search(docs[f+fun], "GTK_") != -1)
+                werror(lines[ f + fun ]+
+                       ": Warning: Possible C-style GTK constant name\n");
+              if( search(docs[f+fun], "gtk_") != -1)
+                if(search( docs[f+fun], "C-") == -1)
+                  werror(lines[ f + fun ]+
+                         ": Warning: Possible C-style GTK function name\n");
+            }
+          }
+	  fd->write("<dd>"+(docs[f+fun]?docs[f+fun]:"")+"</a>\n");
+	}
+      }
+    }
+  }
+
+  if(signals[f] && sizeof(signals[f]))
+  {
+    fd->write("</dl><h2>Signals</h2>\n");
+    fd->write("<dl>");
+    print_signals( signals[f], fd, f );
+  }
+  
+  if(struct[f]["inherit"])
+  {
+    fd->write("</dl><h2>Inherited methods</h2><dl>\n");
+    print_inherited_functions( struct[f]["inherit"], fd );
+    fd->write("</dl><h2>Inherited signals</h2><dl>\n");
+    print_inherited_signals( struct[f]["inherit"], fd );
+  }
+  fd->write("</dl>\n");
+  fd->close();
+}
+
+void print_rec_tree(array plane, mapping t, int ind, object to)
+{
+  foreach(sort(plane), string n)
+  {
+    print_function_defs( n );
+//     werror(" "*ind + n+"\n");
+
+    to->write("<li><a href="+n+".html>"+classname(n)+"</a>");
+    if(t[n])
+    {
+      to->write("<ul>\n");
+      print_rec_tree(sort(t[n]), t, ind+1, to);
+      to->write("</ul>\n");
+    }
+  }
+}
+
+int fnamesfun( string a, string b )
+{
+  return (classname(String.capitalize(lower_case(a))) >
+          classname(String.capitalize(lower_case(b))));
+}
+
+int do_docs;
+array (string) sort_dependencies( array bunch, mapping extra )
+{
+  mapping inheriting = ([]);
+  foreach(bunch, string s)
+  {
+    if(inheriting[extra[s]["inherit"]])
+      inheriting[extra[s]["inherit"]]+=({ s });
+    else
+      inheriting[extra[s]["inherit"]]=({ s });
+  }
+  array (string) result = inheriting[0];
+
+  if(do_docs)
+  {
+    multiset roots=
+      mkmultiset(indices(inheriting))-mkmultiset(`+(@values(inheriting)));;
+
+    mkdir("docs");
+    rm("docs/index.html");
+    object fd = Stdio.File("docs/index.html", "wc");
+    fd->write("<a href=global.html><h1>Global functions</h1></a>\n");
+    fd->write("<h1>Pike GTK Inheritance tree</h1>\n");
+    fd->write("<ul>");
+//     print_function_defs( "global", 1 );
+    foreach(sort(indices(roots)), string r)
+      if(r != "global")
+        print_rec_tree( inheriting[r], inheriting, 1, fd);
+    fd->write("</ul>");
+    fd->write("<h1>All classes in alphabetical order</h1>\n");
+    fd->write("<ul>");
+    mapping ltos=mkmapping(Array.map(indices(struct),String.capitalize),
+                           indices(struct));
+    foreach(Array.sort_array(Array.map(indices(struct), String.capitalize), 
+                             fnamesfun), string s)
+      if(s != "global")
+        fd->write("<li> <a href="+ltos[s]+".html>"+classname(s)+"</a>\n");
+    fd->write("</ul>\n");
+    fd->write("<h1>All constants in alphabetical order</h1>\n");
+    fd->write("<ul>");
+    array consts = 
+      Array.map(constants/"\n", 
+                lambda(string s) {
+                  if((sscanf(s, "%*[^\"]\"%s\"", s)==2) && strlen(s))
+                    return s;
+                }) - ({ 0 });
+    
+    foreach(Array.sort_array(consts,fnamesfun), string s)
+      fd->write("<li> "+classname(String.capitalize(lower_case(s)))+"\n");
+    fd->write("</ul>");
+  }
+  m_delete(inheriting, 0);
+  while(sizeof(inheriting))
+  {
+    int mod;
+    foreach(result, string s)
+    {
+      if(inheriting[s])
+      {
+	result += inheriting[s];
+	m_delete(inheriting, s);
+	mod++;
+      }
+    }
+    if(!mod)
+    {
+      werror("Inconsistend inheritance tree!\n");
+      multiset roots=mkmultiset(indices(inheriting))-mkmultiset(`+(@values(inheriting)));;
+      werror("orphans:\n");
+      foreach(indices(roots), string r)
+      {
+	if(extra[r])
+	  werror("\n+ "+r+"   [ "+extra[r]["inherit"]+"]\n");
+	else
+	  werror("\n+ "+r+" UNDEFINED\n");
+	print_rec_tree( inheriting[r], inheriting, 1, Stdio.stdout);
+      }
+      exit(1);
+    }
+  }
+ return result;
+} 
+string constants="";
+
+string PIKE;
+
+void find_pike()
+{
+  string m = Stdio.read_bytes("config.cache");
+  if(!m) 
+  {
+    werror("Cannot find config.cache!\n");
+    exit(0);
+  }
+  foreach(m/"\n", string l) {
+    if(!sscanf(l, "ac_cv_path_PIKE=${ac_cv_path_PIKE='%s'}", PIKE))
+      sscanf(l, "ac_cv_path_PIKE=${ac_cv_path_PIKE=%s}", PIKE);
+    if(PIKE)
+      break;
+  }
+  if(!PIKE)
+  {
+    werror("Cannot find pike program cache variable in config.cache file.\n");
+    exit(0);
+  }
+}
+
+
+
+string make_example_image(string from, int top)
+{
+  object mei;
+  if(!mei)
+    mei = (object)("make_example_image.pike");
+  if(file_stat( "docs/"+mei->file_name(from)))
+    return mei->tags(from);
+
+  if(!PIKE) 
+    find_pike();
+
+  string res=Process.popen(PIKE+" "+dirname(__FILE__)+
+                           "/make_example_image.pike '"+from+"'"+
+                           (top?" TOP":""));
+  if(!strlen(res))
+  {
+    werror("Failed to make example image from '"+from+"'\n");
+  }
+  return res;
+}
+
+int in_img, img_toplevel;
+string delay_slot="", normal_slot="";
+
+string handle_img(string line)
+{
+  if(line=="toplevel")
+    img_toplevel=1;
+  else if(sscanf(line, "delay: %s", line))
+    delay_slot += line+"\n";
+  else if(line == "img_end" || sscanf(line, "img_end%*s"))
+  {
+    string code = ("lambda() {\n"+"GDK.GC g;\nGTK.Widget w;\n"+ normal_slot+"\n");
+    if(strlen(delay_slot))
+      code += "call_out(lambda(object w,object g) {\n"+delay_slot+"}, 0.05, w,g);\n";
+    code+="return w;\n}()";
+    delay_slot=normal_slot="";
+    in_img = 0;
+    return make_example_image(code,img_toplevel);
+  } else
+    normal_slot += line+"\n";
+  return "";
+}
+
+string find_constants(string prefix)
+{
+  array res = ({});
+  foreach(constants/"\n", string c)
+    if(search(c,prefix) != -1)
+    {
+      sscanf(c, "%*[ \t]%*s\"%s,", c);
+      sscanf(c, "GTK_%s", c);
+      sscanf(c, "%[^\"]", c);
+      res += ({ classname(String.capitalize(lower_case(c))) });
+    }
+
+  if(!sizeof(res)) 
+  {
+    werror("Fatal error: CONST("+prefix+") in doc string: No consts found\n");
+    exit(1);
+  }
+  return String.implode_nicely( res );
+}
+
+
+string g�dsla_med_line(string s, string f)
+{
+  string line = "#line %d \""+f+"\"\n%s\n";
+  int l;
+  string res="";
+  foreach(s/"\n", string d)
+    res += sprintf(line, ++l, d );
+  return res;
+}
+
+string read_indata()
+{
+  string data = g�dsla_med_line(Stdio.read_bytes( dir+"/source/global.pre" ),
+                                dir+"/source/global.pre");
+  foreach(get_dir( dir+"/source"), string f)
+    if( f[-1] == 'c' )
+      emit_nl("#line 1 \""+dir+"/source/"+f+"\"\n"+
+              Stdio.read_bytes( dir+"/source/"+f ));
+    else if(f[-1] == 'e'  && f != "global.pre")
+      data += g�dsla_med_line(Stdio.read_bytes( dir+"/source/"+f ),
+                              dir+"/source/"+f );
+  return data;
+}
+
+multiset options;
+int has_cond_widget( string what )
+{
+  if(!options)
+    options = mkmultiset( (Stdio.read_bytes( "options" )-" ")/"\n" );
+//   werror( "has_cond_widget("+what+") -> "+options[what]+"\n");
+  return options[what];
+}
+
+int odd;
+string build_cursor( string a )
+{
+  int num=0;
+  sscanf( a, "GDK.%s", a );
+  num = master()->resolv("GDK")[a];
+
+  return "<tr bgcolor="+(odd++%2?"#f6e0d0":"#faebd7")+
+    "><td><font color=black>GDK."+a+"</font></td>"
+    "<td><img src=cursor_"+num+".gif></td>"
+    "<td><img src=cursor_"+num+"_inv.gif></td>"
+    "<td><img src=cursor_"+num+"_red.gif></td>"
+    "<td><img src=cursor_"+num+"_red_inv.gif></td>"
+    "<td><img src=cursor_"+num+"_green.gif></td>"
+    "<td><img src=cursor_"+num+"_green_inv.gif></td>"
+    "<td><img src=cursor_"+num+"_blue.gif></td>"
+    "<td><img src=cursor_"+num+"_blue_inv.gif></td>"
+    "</tr>";
+}
+
+
+string dir;
+int main(int argc, array argv)
+{
+  string progname = "global", extra_cpp="";
+  string types;
+  string last_function;
+  int skip_mode;
+  do_docs = argc > 2;
+  
+  foreach( argv[2..], string w )
+  {
+    if( sscanf( w, "--warn-%s", w ) )
+      warn[w] = 1;
+    if( sscanf( w, "--no-warn-%s", w ) )
+      warn[w] = 0;
+  }
+
+  dir = argv[1];
+  head=replace(Stdio.read_bytes(dir+"/pgtk.c.head"),"PROTOTYPES","");
+  int rl;
+  string rf;
+
+#define ERR(X) werror(rf+":"+rl+":  "+X+"\n");
+#define NUMBER_FUNCTION() lines[progname+last_function] = rf+":"+rl
+
+  if(array err = catch {
+
+  foreach(read_indata()/"\n", string line)
+  {
+    string oline = (line-"*");
+    string fn, rest;
+    ln++;
+
+
+    if( line[0..4] == "#line" )
+      sscanf( line, "#line %d \"%s\"", rl, rf );
+
+
+    if(sscanf(line, "END_COND_WIDGET%s", line))
+    {
+      skip_mode=0;
+      continue;
+    }
+    if(skip_mode)
+    {
+      continue;
+    }
+    if(sscanf(line, "COND_WIDGET(%s);", line))
+    {
+      if(!has_cond_widget(line))
+        skip_mode=1;
+    }
+    else if(sscanf(line, "ADD_INCLUDE(%s);", line))
+    {
+      extra_cpp += line+"\n";
+    }
+    else if(sscanf(line, "PROGRAM(%[^)]s)", line))
+    {
+      end_last_program();
+      begin_new_program( line );
+      last_function="";
+      NUMBER_FUNCTION();
+      //       werror("found program "+line+"\n");
+      progname = line;
+      struct[line]= ([]);
+      emit("/* "+oline+" */\n");
+      emit(" /* Class "+line+" */\n");
+    }
+    else if(sscanf(line, "FUNCTION(%s", line)) 
+    {
+      line = reverse(line);
+      sscanf(line, "%*s)%s", line);
+      line = reverse(line);
+      if(sscanf(line, "%s, %s", fn, line) != 2)
+      {
+        ERR("Bad 'FUNCTION' line");
+	exit(1);
+      }
+      last_function=fn;
+      NUMBER_FUNCTION();
+      emit("/* "+oline+" */\n");
+      emit_proto("void pgtk_"+progname+"_"+fn+"(int args)\n");
+      struct[progname][fn] = line;
+      string a,b;
+      sscanf(line, "\"function(%s:%s)\"", a, b);
+      true_types[progname+fn] = ({ b, a });
+    } 
+    else if(sscanf(line, "SIGNAL(%s\")", line)) 
+    {
+      string name;
+      string doc;
+      sscanf(line, "\"%s\",%s", name, doc);
+      sscanf(doc, "%*[ \t]\"%s", doc);
+      if(signals[progname])
+	signals[progname][name] = doc;
+      else
+	signals[progname] = ([ name:doc ]);
+    } 
+    else if(sscanf(line, "INHERIT(%s)", line)) 
+    {
+      emit("/* "+oline+" */\n");
+      struct[progname]["inherit"] = line;
+    } 
+    else if(sscanf(line, "//%s", line)) 
+    {
+      if(do_docs) 
+      {
+
+	sscanf(line, "%*[ \t]%s", line);
+	string a, b;
+	if(in_img)
+	  line = handle_img( line );
+	if(sscanf(line, "img_begin%*s"))
+	{
+	  in_img=1;
+          examples[lower_case(progname)]++;
+	  line="";
+	} 
+	else if(sscanf(line, "IMG: %s", line))
+        {
+	  line = make_example_image(line,0);
+          examples[lower_case(progname)]++;
+        }
+	else if(line[0..4] == "NOIMG")
+        {
+	  line = "";
+          examples[lower_case(progname)]++;
+        }
+	else if(sscanf(line, "TIMG: %s", line))
+        {
+	  line = make_example_image(line,1);
+          examples[lower_case(progname)]++;
+        }
+	else
+        {
+	  while(sscanf(line, "%sCONST(%s)%s", a, b, line)==3)
+	    line = a+find_constants(b)+line;
+	  while(sscanf(line, "%sCURS(%s)%s", a, b, line)==3)
+	    line = a+build_cursor(b)+line;
+	  while(sscanf(line, "%sW(%s)%s", a, b, line)==3)
+	    line = a+"<a href="+lower_case( b )+".html>GTK."+b+"</a>"+line;
+	  while(sscanf(line, "%sGDK(%s)%s", a, b, line)==3)
+	    line = a+"<a href=Gdk"+b+".html>GDK."+b+"</a>"+line;
+        }
+	if(!docs[progname+last_function])
+	  docs[progname+last_function] = line;
+	else
+	  docs[progname+last_function] += "\n"+line;
+      }
+    } 
+    else if(sscanf(line, "CLASSMEMBER(%[^,],%s)", line, string type)) 
+    {
+      type -= " ";
+      line -= " ";
+      last_function="get_"+line;
+      NUMBER_FUNCTION();
+      struct[progname]["get_"+line] = "\"function(void:"+type+")\"";
+      true_types[progname+"get_"+line] = ({ type, "" });
+
+      emit("/* "+oline+" */\n");
+      emit_proto("void pgtk_"+progname+"_get_"+line+"(int args)\n");
+      emit("{\n");
+      emit("  pop_n_elems(args);\n");
+      emit("  push_"+(type=="string"?"text":type)+"( GTK_"+upper_case( progname )+"( THIS->obj )->"+line+");\n");
+      emit("}\n");
+    }
+    else if(sscanf(line, "SETCLASSMEMBER(%[^,],%s)", line, string type)) 
+    {
+      type -= " ";
+      line -= " ";
+      last_function="set_"+line;
+      NUMBER_FUNCTION();
+      struct[progname]["set_"+line] = "\"function("+type+":"+type+")\"";
+      true_types[progname+"set_"+line] = ({ type, type+" to" });
+
+      emit("/* "+oline+" */\n");
+      emit_proto("void pgtk_"+progname+"_set_"+line+"(int args)\n");
+      emit("{\n");
+      emit("  "+type+" to, old;\n");
+      switch( type )
+      {
+       case "int":
+         emit("  get_all_args( \"set_"+line+"\", args, \"%d\", &to );\n");
+         break;
+       case "float":
+         emit("  get_all_args( \"set_"+line+"\", args, \"%f\", &to );\n");
+         break;
+       default:
+         ERR("Cannot setclassmember of type "+type+"!");
+         exit(1);
+      }
+      emit("  old = ( GTK_"+upper_case( progname )+
+           "( THIS->obj )->"+line+");\n");
+      emit("  ( GTK_"+upper_case( progname )+
+           "( THIS->obj )->"+line+") = to;\n");
+      
+      emit("  push_"+(type=="string"?"text":type)+"( old );\n");
+      emit("}\n");
+    }
+    else if(sscanf(line, "SUBWIDGET(%[^,],%s)", line, string type)) 
+    {
+      type -= " ";
+      line -= " ";
+      last_function=line;
+      NUMBER_FUNCTION();
+      struct[progname][line] = "\"function(void:object)\"";
+      true_types[progname+line] = ({ "<a href=\""+lower_case(type)+".html\">"+
+				     classname(lower_case(type))+"</a>", "" });
+
+      emit("/* "+oline+" */\n");
+      emit_proto("void pgtk_"+progname+"_"+line+"(int args)\n");
+      emit("{\n");
+      emit("  pop_n_elems(args);\n");
+      emit("  push_gtkobjectclass( GTK_"+upper_case( progname )+"( THIS->obj )->"+line+", pgtk_"+type+"_program );\n");
+      emit("}\n");
+    } 
+    else if((sscanf(line, "%sCOMPLEX_FUNCTION(%[^,],%s)",
+                    rest,fn,types)==3)  ||
+            ((sscanf(line, "%sCOMPLEX_FUNCTION(%[^,)])",
+                     rest,fn)==2)&&(types="")))
+    {
+      string return_type;
+      string argument_list = "";
+      string fundef = "";
+      string format_string="";
+      string args="";
+      string sargs="", pre_call="";
+      string post = "", fin="", zap="";
+      int na, i_added;
+      
+      sscanf(rest, "%*[\t ]%[^ \t]", rest);
+      if(!strlen(rest))
+      {
+        rest = 0;
+        return_type = classname(progname);
+      } else
+        return_type = rest;
+
+      if(rest == "/*" || rest == "*")
+        continue;
+      last_function=fn;
+      NUMBER_FUNCTION();
+      if(fn == "create")
+	fin = " pgtk__init_object( fp->current_object );\n";
+
+      foreach(((types-" ")/"," - ({""})), string t)
+      {
+	na++;
+	switch(lower_case(t))
+	{
+	 case "null":
+	   sargs += ", NULL";
+	   break;
+	 case "callback":
+	   fundef += ",function,mixed";
+	   argument_list += ", function(mixed:mixed), mixed";
+	   format_string += "%*%*";
+	   args += ("  struct signal_data *b;\n"
+	            "struct svalue *tmp1, *tmp2;\n");
+	   post += ("  b = malloc(sizeof(struct signal_data));\n"
+		    "  assign_svalue_no_free( &b->cb, tmp1 );\n"
+		    " assign_svalue_no_free( &b->args, tmp2 );\n");
+	   sargs += ",&tmp1,&tmp2";
+	   break;
+
+	 case "stringarray":
+           if(!i_added++)
+             args += "  int _i;\n";
+	   fundef += ",array(string)";
+	   argument_list += ", array(string)";
+	   format_string += "%a";
+	   args += "  struct array *_arg"+na+";\n";
+	   args += "  char **arg"+na+";\n";
+	   sargs += ", &_arg"+na;
+	   fin += " free(arg"+na+");\n";
+	   post += ("  arg"+na+"=malloc(sizeof(char *)* (_arg"+na+"->size));\n"
+		    "  for(_i=0; _i<_arg"+na+"->size; _i++)\n"
+		    "  {\n"
+		    "    if(_arg"+na+"->item[_i].type != T_STRING)\n"
+		    "    {\n"
+		    "      free(arg"+na+");\n"
+		    "      error(\"Wrong type array argument.\\n\");\n"
+		    "    }\n"
+		    "    arg"+na+"[_i] = _arg"+na+"->item[_i].u.string->str;\n"
+		    "  }\n");
+	   break;
+	 case "floatarray":
+	   string size = ", ^^arg"+na+"->size";
+           if(!i_added++)
+             args += "  int _i;\n";
+	   fundef += ",array(float)";
+	   argument_list += ", array(float)";
+	   format_string += "%a";
+	   args += "  struct array *_arg"+na+";\n";
+	   args += "  gfloat *arg"+na+";\n";
+	   zap += size;
+	   fin += " free(arg"+na+");\n";
+	   sargs += (size+", &_arg"+na);
+	   post += ("  arg"+na+"=malloc(sizeof(gfloat)* (_arg"+na+"->size));\n"
+		    "  for(_i=0; _i<_arg"+na+"->size; _i++)\n"
+		    "  {\n"
+		    "    if(_arg"+na+"->item[_i].type != T_FLOAT)\n"
+		    "    {\n"
+		    "      free(arg"+na+");\n"
+		    "      error(\"Wrong type array argument. Expected float\\n\");\n"
+		    "    }\n"
+		    "    arg"+na+"[_i] = _arg"+na+"->item[_i].u.float_number;\n"
+		    "  }\n");
+	   break;
+	 case "intarray":
+	   string size = ", ^^arg"+na+"->size";
+           if(!i_added++)
+             args += "  int _i;\n";
+	   fundef += ",array(int)";
+	   argument_list += ", array(int)";
+	   format_string += "%a";
+	   args += "  struct array *_arg"+na+";\n";
+	   args += "  gint *arg"+na+";\n";
+	   zap += size;
+	   fin += " free(arg"+na+");\n";
+	   sargs += (",&_arg"+na);
+	   post += ("  arg"+na+"=malloc(sizeof(gint)* (1+_arg"+na+"->size));\n"
+		    "  for(_i=0; _i<_arg"+na+"->size; _i++)\n"
+		    "  {\n"
+		    "    if(_arg"+na+"->item[_i].type != T_INT)\n"
+		    "    {\n"
+		    "      free(arg"+na+");\n"
+		    "      error(\"Wrong type array argument. Expected int\\n\");\n"
+		    "    }\n"
+		    "    arg"+na+"[_i] = _arg"+na+"->item[_i].u.integer;\n"
+		    "  }\n"
+                    "  arg"+na+"[_i] = 0;\n");
+	   break;
+	 case "int":
+	   argument_list += ", int";
+#if __VERSION__ >= 0.7
+	   fundef += ",mixed";
+	   format_string += "%D";
+#else
+	   fundef += ","+t;
+	   format_string += "%d";
+#endif
+	   args += "  int arg"+na+";\n";
+	   sargs += ", &arg"+na;
+	   break;
+	 case "intp":
+	   argument_list += ", int";
+#if __VERSION__ >= 0.7
+	   fundef += ",mixed";
+	   format_string += "%D";
+#else
+	   fundef += ",int";
+	   format_string += "%d";
+#endif
+	   args += "  int _arg"+na+", *arg"+na+"=&_arg"+na+";\n";
+	   sargs += ", _arg"+na;
+	   break;
+	 case "float":
+	   argument_list += ", float";
+#if __VERSION__ >= 0.7
+	   fundef += ",mixed";
+	   format_string += "%F";
+#else
+	   fundef += ",float";
+	   format_string += "%f";
+#endif
+	   args += "  float arg"+na+";\n";
+	   sargs += ", &arg"+na;
+	   break;
+	 case "string":
+	   fundef += ","+t;
+	   argument_list += ", string";
+	   format_string += "%s";
+	   args += "  char *arg"+na+";\n";
+	   sargs += ", &arg"+na;
+	   break;
+	 default:
+           if (sscanf(t,"stringarray/%s",t))
+	   {
+	      if(!i_added++)
+		 args += "  int _i;\n";
+	      fundef += ",array(string)";
+	      argument_list += ", array(string)";
+	      format_string += "%a";
+	      args += "  struct array *_arg"+na+";\n";
+	      args += "  char **arg"+na+";\n";
+	      sargs += ", &_arg"+na;
+	      post += ("  if (_arg"+na+"->size != "+
+		       (t=replace(t,({"{","}"}),({"(",")"})))+
+		       ") \n"
+		       "    error(\"argument "+na+" (array(string)) has wrong size (columns=%d, elements=%d)\n\","+t+",_arg"+na+"->size);"
+		       "  arg"+na+"=alloca(sizeof(char *)* (_arg"+na+"->size));\n"
+		       "  for(_i=0; _i<_arg"+na+"->size; _i++)\n"
+		       "  {\n"
+		       "    if(_arg"+na+"->item[_i].type != T_STRING)\n"
+		       "      error(\"Wrong type array argument.\\n\");\n"
+		       "    arg"+na+"[_i] = _arg"+na+"->item[_i].u.string->str;\n"
+		       "  }\n");
+	      break;
+	   }
+
+           int star = sscanf(t, "*%s", t);
+           int optional = sscanf(t, "?%s", t) && __VERSION__ >= 0.7;
+	   fundef += ",object|int";
+	   argument_list+=", "+classname(String.capitalize(lower_case(t)));
+           if(optional) 
+             argument_list += "|null";
+           if(!optional)
+             format_string += "%o";
+           else
+             format_string += "%O";
+           if(sscanf( t, "Gdk%s", t ))
+           {
+             t = String.capitalize(lower_case(t));
+             args += "  struct object *_arg"+na+";\n";
+             args += "  Gdk"+t+" *arg"+na+";\n";
+             sargs += ", &"+(star?"*":"")+"_arg"+na;
+             post+=(" arg"+na+" = get_gdkobject( _arg"+na+", "+t+");\n");
+             if(!optional)
+               post +=("  if(!arg"+na+") error(\"Argument "+
+                       na+": Wanted GDK object of type "+t+".\\n\");\n");
+           } else {
+             args += "  struct object *_arg"+na+";\n";
+             args += "  "+sillycaps(t)+" *arg"+na+";\n";
+             sargs += ", &"+(star?"*":"")+"_arg"+na;
+             if(optional)
+               post += "  if(_arg"+na+")\n  ";
+             post+=(" arg"+na+" = GTK_"+upper_case(t)+"(get_pgtkobject(_arg"+
+                    na+", pgtk_"+lower_case(t)+"_program ) );\n");
+             if(optional)
+               post += " else\n    arg"+na+" = NULL;\n";
+             else
+               post += ("  if(!arg"+na+") error(\"Argument "+
+                        na+": Wanted GTK object of type "+t+".\\n\");\n");
+           }
+           break;
+	}
+      }
+      
+      emit( "/* "+oline+" */\n");
+      emit_proto("void pgtk_"+progname+"_"+fn+"(int args)\n");
+      emit("{\n");
+
+      string srt;
+      switch(rest)
+      {
+       case 0: srt = "object"; break;
+       case "float": srt="float"; emit("  float result;\n"); break;
+       case "int": srt="int";emit("  int result;\n"); break;
+       case "string": srt="string"; emit("  gchar *result;\n"); break;
+       default: 
+         emit("  void *result;  /* "+rest+" */\n"); 
+         srt = "object";
+         break;
+      }
+
+      true_types[progname+fn] = ({ return_type, argument_list[2..] });
+      struct[progname][fn] = "\"function("+
+                           (strlen(fundef[1..])?fundef[1..]:"void")
+                           +":"+srt+")\"";
+
+      if(na)
+      {
+	emit( args );
+        if( fn == "create" )
+          emit( "  if( !pigtk_is_setup )\n"
+                "      error(\"You must call GTK.setup_gtk( argv ) first"
+                "\\n\");\n");
+	emit( "  get_all_args(\""+progname+"->"+fn+"\", args, \""+
+	      format_string+"\""+((sargs-"*")-zap)+");\n");
+	sargs = replace(sargs,"&tmp1,&tmp2","(void *)pgtk_button_func_wrapper, b");
+	emit(post);
+      }
+      if(fn == "create") 
+      {
+	emit("  if(THIS->obj) error(\"create called more than once\\n\");\n");
+	emit("  THIS->obj = GTK_OBJECT( gtk_"+progname+"_new("+
+	     replace((sargs[1..]-"&")-"_","^^","_")+" ) );\n");
+	emit("  if(!THIS->obj) error(\"Failed to initiate "+progname+"\\n\");\n");
+      }
+      else
+      {
+	emit("  if(!THIS->obj)\n"
+	     "    error(\"Calling function in unitiated object\\n\");\n");
+        if(rest)
+          emit("  result = ");
+        else
+          emit( "  " );
+	emit("gtk_"+progname+"_"+fn+"( GTK_"+upper_case(progname)+
+	     "( THIS->obj )"+replace((sargs-"&")-"_","^^","_")+" );\n");
+      }
+      if(strlen(fin)) 
+        emit(fin+"\n");
+      emit("  pop_n_elems(args);\n");
+      if(!rest)
+      {
+        emit("  ref_push_object( fp->current_object );\n");
+      } else {
+        switch(rest)
+        {
+         case "float":
+           emit( "  push_float( result );\n" );
+           break;
+         case "int":
+           emit( "  push_int( result );\n" );
+           break;
+         case "void":
+           emit( "  push_int( 0 );\n" );
+           break;
+         case "string":
+           emit( "  if(result) push_text( result ); else push_int( 0 );\n" );
+           break;
+         default:
+           if(sscanf( rest, "GDK.%s", rest ))
+           {
+             emit("  push_pgdkobject( result, pgtk_Gdk"+
+                  String.capitalize(lower_case(rest))+"_program);\n");
+           } else {
+             sscanf(rest, "GTK.%s", rest );
+             emit("  push_gtkobjectclass( result, "+
+                  "pgtk_"+lower_case(rest)+"_program );\n");
+           }
+        }
+      }
+      emit("}\n\n");
+    } else if(sscanf(line, "CONSTANT(%s)", line)==1) {
+      if(!sscanf(line, "GTK_%s", fn))
+	fn = line;
+      constants += ("  add_integer_constant(\""+fn+"\", "+line+", 0);\n");
+    } else if(sscanf(line, "SIMPLE%sFUNCTION(%s)", line, fn)==2) {
+      last_function=fn;
+      NUMBER_FUNCTION();
+      emit("/* "+oline+" */\n");
+      emit_proto("void pgtk_"+progname+"_"+fn+"(int args)\n");
+      emit("{\n");
+      switch(line)
+      {
+       case "_":
+	 /* void function.... */
+	 true_types[progname+fn] = ({ classname(progname), "" });
+	 struct[progname][fn] = "\"function(void:object)\"";
+	 emit("  if(!THIS->obj)\n"
+	      "    error(\"Calling function in unitiated object\\n\");\n");
+	 emit("  gtk_"+progname+"_"+fn+"(GTK_"+upper_case(progname)+"(THIS->obj));\n");
+	 break;
+       case "_INT_":
+	 emit("  int i;\n");
+	 struct[progname][fn] = "\"function(int:object)\"";
+	 true_types[progname+fn] = ({ classname(progname), "int" });
+	 emit("  if(!THIS->obj)\n"
+	      "    error(\"Calling function in unitiated object\\n\");\n");
+#if __VERSION__ >= 0.7
+	 emit("  get_all_args(\""+progname+"->"+fn+"\",args, \"%D\", &i);\n");
+#else
+	 emit("  get_all_args(\""+progname+"->"+fn+"\",args, \"%d\", &i);\n");
+#endif
+	 emit("  gtk_"+progname+"_"+fn+"( GTK_"+upper_case(progname)+
+	      "( THIS->obj ), i );\n");
+	 break;
+       default:
+	 line-="_";
+	 emit("  struct object *o;\n");
+	 struct[progname][fn] = "\"function(object:object)\"";
+	 true_types[progname+fn]=({ classname(progname), 
+				    "<a href=\""+lower_case(line)+".html\">"+
+				    classname(lower_case(line))+"</a>" });
+	 emit("  GtkObject *f;\n");
+	 emit("  if(!THIS->obj)\n"
+	      "    error(\"Calling function in unitiated object\\n\");\n");
+	 emit("  get_all_args(\""+progname+"->"+fn+"\", args, \"%o\", &o);\n");
+	 emit("  f = get_gtkobject( o );\n");
+	 emit("  if(!f)\n"
+	      "    error(\"Expected "+classname(line)+", got NULL\\n\");\n");
+	 emit("  gtk_"+progname+"_"+fn+"( GTK_"+upper_case(progname)+"( THIS->obj ), GTK_"+upper_case(line)+"( f ) );\n");
+      }
+
+      emit("  pop_n_elems(args);\n");
+      emit("  ref_push_object( fp->current_object );\n");
+      emit("}\n");
+    } else if(sscanf(line, "ARGS(%s);", line)==1) {
+      true_types[progname+last_function][1] = line;
+    } else if(sscanf(line, "RETURNS(%s);", line)==1) {
+      true_types[progname+last_function][0] = line;
+    } else if(sscanf(line, "NAME_ARGS(%s);", line)==1) {
+      array a = line / ",";
+      array b = true_types[progname+last_function][1] / ",";
+      int i;
+      string res="";
+      for(i=0; i<min(sizeof(a),sizeof(b)); i++)
+	res += ","+b[i]+" "+a[i];
+      true_types[progname+last_function][1] = res[1..];      
+      named[progname+last_function] = 1;
+    } else {
+      emit(line+"\n");
+    }
+  }
+  })
+  {
+    ERR("Fatal error on: "+describe_backtrace(err));
+    exit(1);
+  }
+  string pre="";
+
+  end_last_program();
+  /* global stuff.. */
+  no_hashline=1;
+
+  emit_nl(extra_cpp);
+  emit_nl("void clear_obj_struct(struct object *o)\n{\n");
+  emit_nl("  MEMSET(fp->current_storage, 0, sizeof(struct object_wrapper));\n");
+  emit_nl("}\n");
+  emit_nl("void pike_module_init()\n{\n");
+  emit_nl(constants);
+
+  foreach(sort(indices(`+(@values(signals)))), string s)
+    emit_nl("  add_string_constant( \"s_"+s+"\", \""+s+"\", 0 );\n");
+  
+  emit_program_block( struct->global, "global" );
+  if(!do_docs)
+    m_delete(struct, "global");
+
+  if(do_docs)
+  {
+    foreach(get_dir(dir+"/pcdocs"), string d)
+    {
+      string last_function, progname, a, b;
+      int ln;
+      if(Stdio.file_size(dir+"/pcdocs/"+d) < 1)
+        continue;
+
+#undef  NUMBER_FUNCTION
+#define NUMBER_FUNCTION() lines[progname+last_function] = "pcdocs/"+d+":"+ln
+      foreach(Stdio.read_bytes(dir+"/pcdocs/"+d)/"\n", string line)
+      {
+        ln++;
+        if(sscanf(line, "PROGRAM(%s);", line))
+        {
+          last_function ="";
+          progname = line;
+          NUMBER_FUNCTION();
+          struct[line] = ([]);
+        } else if(sscanf(line, "INHERIT(%s)", line)) {
+          struct[progname]["inherit"] = line;
+        } else if(sscanf(line, "FUNCTION(%s", line)) {
+          string fn;
+          line = reverse(line);
+          sscanf(line, "%*s)%s", line);
+          line = reverse(line);
+          if(sscanf(line, "%s, %s", fn, line) != 2)
+          {
+            werror("Bad 'FUNCTION' line '"+line+"' in file "+d+"; line "+ln+"\n");
+            exit(1);
+          }
+          last_function=fn;
+          NUMBER_FUNCTION();
+          struct[progname][fn] = line;
+          sscanf(line, "\"function(%s:%s)\"", a, b);
+          true_types[progname+fn] = ({ b, a });
+        } else if(sscanf(line, "SIGNAL(%s\")", line)) {
+          string name;
+          string doc;
+          sscanf(line, "\"%s\",%s", name, doc);
+          sscanf(doc, "%*[ \t]\"%s", doc);
+          if(signals[progname])
+            signals[progname][name] = doc;
+          else
+            signals[progname] = ([ name:doc ]);
+        } else if(sscanf(line, "//%s", line)) {
+          sscanf(line, "%*[ \t]%s", line);
+          string a, b;
+          if(in_img)
+            line = handle_img( line );
+          if(sscanf(line, "img_begin%*s"))
+          {
+            examples[progname]++;
+            in_img=1;
+            line="";
+          } 
+          else if(sscanf(line, "IMG: %s", line))
+          {
+            line = make_example_image(line,0);
+            examples[progname]++;
+          }
+          else if(sscanf(line, "TIMG: %s", line))
+          {
+            line = make_example_image(line,1);
+            examples[progname]++;
+          }
+          else
+            while(sscanf(line, "%sCONST(%s)%s", a, b, line)==3)
+              line = a+find_constants(b)+line;
+          if(!docs[progname+last_function])
+            docs[progname+last_function] = line;
+          else
+            docs[progname+last_function] += "\n"+line;
+        } else if(sscanf(line, "SUBWIDGET(%[^,],%s)", line, string type)) {
+          type -= " ";
+          line -= " ";
+          last_function=line;
+          NUMBER_FUNCTION();
+          struct[progname][line] = "\"function(void:object)\"";
+          true_types[progname+line] = ({ "<a href=\""+lower_case(type)+".html\">"+
+                                         classname(lower_case(type))+"</a>", "" });
+        } else if(sscanf(line, "ARGS(%s);", line)==1) {
+          true_types[progname+last_function][1] = line;
+        } else if(sscanf(line, "RETURNS(%s);", line)==1) {
+          true_types[progname+last_function][0] = line;
+        } else if(sscanf(line, "NAME_ARGS(%s);", line)==1) {
+          array a = line / ",";
+          array b = true_types[progname+last_function][1] / ",";
+          int i;
+          string res="";
+          for(i=0; i<min(sizeof(a),sizeof(b)); i++)
+            res += ","+b[i]+" "+a[i];
+          true_types[progname+last_function][1] = res[1..];      
+          named[progname+last_function] = 1;
+        }
+      }
+    }
+  }
+
+  werror(sizeof(struct)+" classes\n");
+  werror(sizeof(constants/"\n")+" constants\n");
+  werror(sizeof(signals)+" signal constants (strings)\n");
+
+  string to_free="";
+  foreach(sort_dependencies(indices(struct),struct), string w)
+  {
+    mapping q = struct[w];
+    emit_nl("\n\n  start_new_program(); /* "+String.capitalize(w)+" */\n");
+    to_free += "  free_program( pgtk_"+w+"_program );\n";
+    if(q["inherit"])
+    {
+      emit_nl("   low_inherit( pgtk_"+q["inherit"]+"_program, 0,0,0,0,0);\n");
+      m_delete(q, "inherit");
+    }
+    else
+    {
+#if __VERSION__ > 0.6
+      emit_nl("  ADD_STORAGE(struct object_wrapper);\n");
+#else
+      emit_nl("  add_storage(sizeof(struct object_wrapper));\n");
+#endif
+    }
+    emit_nl("   set_init_callback(clear_obj_struct);\n");
+    emit_program_block( q, w );
+    emit_nl("  add_program_constant(\""+String.capitalize(w)+"\",\n"
+	    "                       (pgtk_"+w+"_program = end_program()), 0);"
+	    "\n");
+    pre += "/*ext*/ struct program *pgtk_"+w+"_program;\n";
+  }
+  werror(_num_functions+" functions\n");
+  emit_nl("}\n\n");
+  emit_nl("\nvoid pike_module_exit()\n{\n"+to_free+"}\n\n");
+  files += "pgtk.c ";
+  if(!do_docs)
+  {
+    string q =replace(Stdio.read_bytes(dir+"/pgtk.c.head"), "PROTOTYPES", 
+                      replace(pre, "/*ext*/ ", ""));
+    pre = replace(pre, "/*ext*/", "extern");
+    if(!equal(sort((Stdio.read_bytes("prototypes.h") || "")/"\n"), sort(pre/"\n")))
+    {
+      rm("prototypes.h");
+      werror("prototypes.h was modified\n");
+      Stdio.write_file("prototypes.h", pre);
+    }
+    q+=(sort(glob_prototypes/"\n")*"\n") + "\n\n" + buffer;
+    if(!equal(sort((Stdio.read_bytes("pgtk.c") || "")/"\n"),
+	      sort(q/"\n")))
+    {
+      werror("pgtk.c modified\n");
+      object outf = Stdio.File("pgtk.c", "rwct");
+      outf->write(q);
+    }
+  }
+  rm("files_to_compile");
+  Stdio.write_file("files_to_compile", replace(files, ".c", ".o"));
+}
+
+
diff --git a/src/post_modules/GTK/configure.in b/src/post_modules/GTK/configure.in
new file mode 100644
index 0000000000000000000000000000000000000000..2dcb1c74df24cb1d623b2bff5b0535debbcc1a89
--- /dev/null
+++ b/src/post_modules/GTK/configure.in
@@ -0,0 +1,140 @@
+AC_INIT(build_pgtk.pike)
+AC_CONFIG_HEADER(config.h)
+
+AC_MODULE_INIT()
+
+AC_CHECK_FUNCS( gethrtime signal sigaction )
+
+AC_HEADER_STDC
+AC_CHECK_HEADERS( signal.h arpa/inet.h )
+
+AM_PATH_GTK(1.1.13,[WITH_GTK=1],W[ITH_GTK=0])
+
+if /bin/test "x$WITH_GTK" = x1 ; then
+AC_SUBST(WITH_GTK)
+WITH_GTK=1
+
+AC_SUBST(PGTK_CFLAGS)
+AC_SUBST(PGTK_LIBS)
+PGTK_CFLAGS="$GTK_CFLAGS"
+PGTK_LIBS="$GTK_LIBS"
+
+CFLAGS="$CFLAGS $GTK_CFLAGS"
+LIBS="$MODULE_LDFLAGS $LIBS"
+
+AC_SUBST(pgtk_has_sheet)
+AC_CHECK_LIB(GtkSheet, main,,,`gtk-config --libs`)
+if test x$ac_cv_lib_GtkSheet_main = xyes ; then
+  pgtk_has_sheet=sheet
+  echo "**********************************"
+  echo "Enabling GTK.Sheet related widgets"
+  if test -f `gtk-config --prefix`/lib/libGtkSheet.a ; then 
+    echo "Forcing addition of .a file to our .so file"
+    LIBS="$LIBS `gtk-config --prefix`/lib/libGtkSheet.a"
+  fi
+  echo "**********************************"
+else
+  pgtk_has_sheet=nosheet
+  unset ac_cv_lib_GtkSheet_main
+  echo "*********************************************"
+  echo " Failed to find the GTK Sheet widget. If you "
+  echo " need it, you can download it from           "
+  echo " ftp://ripley.ifir.edu.ar/pub/gtk/gtksheet/  "
+  echo " When you have installed it, rerun configure "
+  echo "*********************************************"
+fi
+
+dnl Check for GL/MesaGL libraries
+AC_ARG_WITH(GL-prefix,  [  --with-GL-prefix=DIR    Prefix where GL/MesaGL is installed])
+AC_ARG_WITH(lib-GL,     [  --with-lib-GL           use '-lGL'])
+AC_ARG_WITH(lib-MesaGL, [  --with-lib-MesaGL       use '-lMesaGL'])
+
+if test "x$with_GL_prefix" = "x" ; then
+ GL_LDOPTS=""
+ GL_CFLAGS=""
+else
+ GL_LDOPTS="-L$with_GL_prefix/lib"
+ GL_CFLAGS="-I$with_GL_prefix/include"
+fi
+
+saved_LIBS="$LIBS"
+
+AC_MSG_CHECKING([OpenGL])
+
+LIBS="$saved_LIBS $GL_LDOPTS -lGL"
+AC_TRY_LINK( ,[ char glBegin(); glBegin(); ], have_GL=yes, have_GL=no)
+AC_MSG_RESULT($have_GL)
+
+if test "x$have_GL" = "xno" ; then
+  AC_MSG_CHECKING([Mesa])
+  LIBS="$saved_LIBS $GL_LDOPTS -lMesaGL"
+  AC_TRY_LINK( ,[ char glBegin(); glBegin(); ], have_MesaGL=yes, have_MesaGL=no)
+  AC_MSG_RESULT($have_MesaGL)
+
+  if test "x$have_MesaGL" = "xno"; then
+   AC_MSG_CHECKING([Mesa with pthreads])
+   LIBS="$saved_LIBS $GL_LDOPTS -lMesaGL -lpthread"
+   AC_TRY_LINK( ,[ char glBegin(); glBegin(); ], have_MesaGL_pthread=yes, have_MesaGL_pthread=no)
+   AC_MSG_RESULT($have_MesaGL_pthread)
+  fi
+fi
+
+LIBS="$saved_LIBS"
+
+
+if test "x$with_lib_GL" = "xyes"; then
+
+ if test "x$have_GL" = "xyes"; then
+  GL_LIBS="$GL_LDOPTS  -lGL"
+ else
+  AC_MSG_ERROR([Missing GL library])
+ fi
+
+elif test "x$with_lib_MesaGL" = "xyes"; then
+
+ if test "x$have_MesaGL" = "xyes"; then
+  GL_LIBS="$GL_LDOPTS -lMesaGL"
+ elif test "x$have_MesaGL_pthread" = "xyes"; then
+  GL_LIBS="$GL_LDOPTS -lMesaGL -lpthread"
+ else
+  AC_MSG_ERROR([Missing MesaGL library])
+ fi
+
+else
+
+ if test "x$have_GL" = "xyes"; then
+  GL_LIBS="$GL_LDOPTS -lGL"
+ elif test "x$have_MesaGL" = "xyes"; then
+  GL_LIBS="$GL_LDOPTS  -lMesaGL"
+ elif test "x$have_MesaGL_pthread" = "xyes"; then
+  GL_LIBS="$GL_LDOPTS  -lMesaGL -lpthread"
+ else
+  have_GL=no
+ fi
+
+fi
+
+CFLAGS="$GL_CFLAGS $CFLAGS"
+
+AC_SUBST(pgtk_has_glarea)
+pgtk_has_glarea=noglarea
+
+if test "x$have_GL" = "xyes" ; then
+  AC_CHECK_LIB(gtkgl, main,,,`gtk-config --libs` $GL_LIBS)
+  if test x$ac_cv_lib_gtkgl_main = xyes ; then
+    pgtk_has_glarea=glarea
+    LIBS="$GL_LIBS $LIBS"
+  else
+    unset ac_cv_lib_gtkgl_main
+    echo "*********************************************"
+    echo " Warning: Failed to find the GTK GL widget.  "
+    echo " GL-support will be disabled.                "
+    echo " The widget is available from                "
+    echo " "
+    echo "*********************************************"
+  fi
+fi
+
+fi
+
+AC_OUTPUT(Makefile options)
diff --git a/src/post_modules/GTK/dependencies b/src/post_modules/GTK/dependencies
new file mode 100644
index 0000000000000000000000000000000000000000..67affef0b209e3dd582e52485c96955997cd0f76
--- /dev/null
+++ b/src/post_modules/GTK/dependencies
@@ -0,0 +1 @@
+# No, there is no way to fix these, really.
\ No newline at end of file
diff --git a/src/post_modules/GTK/dummy.c b/src/post_modules/GTK/dummy.c
new file mode 100644
index 0000000000000000000000000000000000000000..4d71c29d2dc868b8f4af61416e714fadc5d572d1
--- /dev/null
+++ b/src/post_modules/GTK/dummy.c
@@ -0,0 +1,13 @@
+#include "global.h"
+#include "config.h"
+
+RCSID("$Id: dummy.c,v 1.1 1999/11/07 01:38:48 per Exp $");
+
+/* Well... Sort of basic, right? :-) */
+void pike_module_init()
+{
+}
+
+void pike_module_exit()
+{
+}
diff --git a/src/post_modules/GTK/dump_cursors.pike b/src/post_modules/GTK/dump_cursors.pike
new file mode 100644
index 0000000000000000000000000000000000000000..34f44eae95023ccef5dcc8f880ea29c4ece723cd
--- /dev/null
+++ b/src/post_modules/GTK/dump_cursors.pike
@@ -0,0 +1,92 @@
+object da, fn, gc, ia, w;
+string prefix;
+
+#define GRAB(i) Image.PNM.decode(ia->grab(w,4,4+(i*80),60,60)->get_pnm())
+
+void grab_2( int x )
+{
+  call_out( grab, 0.001, x+2 );
+
+  object l = Image.Layer( GRAB(0), GRAB(1)->invert() );
+  l = l->autocrop();
+  
+  mkdir("cursors");
+  Stdio.File( prefix+x+".gif", "wct")->
+    write(Image.GIF.encode_trans( l->image(),l->alpha() ) );
+
+
+  Stdio.File( prefix+x+"_red.gif", "wct")->
+    write(Image.GIF.encode_trans( l->image()->change_color(Image.Color.black,
+                                                           Image.Color.red),
+                                  l->alpha() ) );
+
+  Stdio.File( prefix+x+"_green.gif", "wct")->
+    write(Image.GIF.encode_trans( l->image()->change_color(Image.Color.black,
+                                                           Image.Color.green),
+                                  l->alpha() ) );
+
+  Stdio.File( prefix+x+"_blue.gif", "wct")->
+    write(Image.GIF.encode_trans( l->image()->change_color(Image.Color.black,
+                                                           Image.Color.blue),
+                                  l->alpha() ) );
+
+
+  Stdio.File( prefix+x+"_red_inv.gif", "wct")->
+    write(Image.GIF.encode_trans( l->image()->change_color(Image.Color.black,
+                                                           Image.Color.red)
+                                  ->change_color(Image.Color.white,
+                                                 Image.Color.black),
+                                  l->alpha() ) );
+
+  Stdio.File( prefix+x+"_green_inv.gif", "wct")->
+    write(Image.GIF.encode_trans( l->image()->change_color(Image.Color.black,
+                                                           Image.Color.green)
+                                  ->change_color(Image.Color.white,
+                                                 Image.Color.black),
+                                  l->alpha() ) );
+
+  Stdio.File( prefix+x+"_blue_inv.gif", "wct")->
+    write(Image.GIF.encode_trans( l->image()->change_color(Image.Color.black,
+                                                           Image.Color.blue)
+                                  ->change_color(Image.Color.white,
+                                                 Image.Color.black),
+                                  l->alpha() ) );
+
+  Stdio.File( prefix+x+"_inv.gif", "wct")->
+    write(Image.GIF.encode_trans( l->image()->invert(),l->alpha() ) );
+
+}
+
+void grab( int x )
+{
+  if( x > 152 ) _exit(0);
+  if(!file_stat( prefix+x+".gif" ) )
+  {
+    if(!da)
+    {
+      GTK.setup_gtk();
+      w = GTK.Window( GTK.WindowToplevel );
+      w->add( da = GTK.DrawingArea( ) );
+      da->set_usize( 100,400 );
+      w->show_all();
+      GTK.flush();
+      fn = GDK.Font( "cursor" );
+      gc = GDK.GC( da );
+      ia = GDK.Image( );
+      da->set_app_paintable( 1 );
+      da->set_background( GDK.Color( @(array)Image.Color.white ) );
+    }
+    da->clear();
+    da->draw_text( gc, fn, 30,30, sprintf("%c", x ) );
+    da->draw_text( gc, fn, 30,80+30, sprintf("%c", x+1 ) );
+    call_out( grab_2, 0.01, x );
+  } else
+     grab( x+2 );
+}
+
+int main(int c, array argv)
+{
+  prefix = argv[1];
+  grab(0);
+  return -1;
+}
diff --git a/src/post_modules/GTK/examples/gcolor.pike b/src/post_modules/GTK/examples/gcolor.pike
new file mode 100644
index 0000000000000000000000000000000000000000..616ba553bc3681c8f10aa8ae4e9d0e0941b29173
--- /dev/null
+++ b/src/post_modules/GTK/examples/gcolor.pike
@@ -0,0 +1,82 @@
+#!/usr/local/bin/pike
+object win, button, frame, vbox, cs, edit, edit2;
+int not_now=0;
+
+void cs_changed(int foo, object w)
+{
+  [float r, float g, float b, float a] = w->get_color();
+  edit->set_text(sprintf("#%02x%02x%02x",
+                         (int)(r*255+0.5),(int)(g*255+0.5),(int)(b*255+0.5)));
+  edit2->set_text(sprintf("({ %d, %d, %d })",
+                          (int)(r*255+0.5), (int)(g*255+0.5),
+                          (int)(b*255+0.5)));
+}
+
+void edit_changed(int foo, object w)
+{
+  if(not_now)
+  {
+    not_now = 0;
+    return;
+  }
+  
+  string t = w->get_text();
+  array c;
+  c = array_sscanf(t, "#%02x%02x%02x");
+  if(sizeof(c)!=3&&w==edit2)
+    catch {
+      c = compile_string("array foo() { return "+t+";}")()->foo();
+    };
+  if(sizeof(c) != 3) return;
+
+  array cv = cs->get_color()[..2];
+   if(equal(Array.map(cv, lambda(float c){return (int)(c*255+0.5);}), c))
+    return;
+
+   not_now = 1;
+   cs->set_color( Array.map(c, `/, 255.0) );
+
+  if(w == edit)
+    edit2->set_text(sprintf("({ %d, %d, %d })", @c));
+  else
+    edit->set_text(sprintf("#%02x%02x%02x", @c));
+}
+
+
+int main()
+{
+  GTK.setup_gtk( "Ultra Colorselector++" );
+  if(file_stat( getenv("HOME")+"/.pgtkrc" ))
+    GTK.parse_rc( cpp(Stdio.read_bytes(getenv("HOME")+"/.pgtkrc")) );
+  win = GTK.Window( GTK.WindowToplevel );
+
+  edit = GTK.Entry();
+  edit2 = GTK.Entry();
+  cs = GTK.Color_selection();
+
+  cs->signal_connect("color_changed",cs_changed,0);
+  ({edit,edit2})->signal_connect("changed",edit_changed,0);
+
+  frame = GTK.Frame(  );
+  vbox = GTK.Vbox(0,0);
+
+  vbox->set_homogeneous( 0 );
+  object hbox=GTK.Hbox( 0, 0 );
+  vbox->add(cs);
+  vbox->set_child_packing( cs, 1, 1, 0, 0 );
+  vbox->add(hbox);
+  vbox->set_child_packing( hbox, 0, 0, 0, 0 );
+
+  hbox->add(edit);
+  hbox->add(edit2);
+  frame->add(vbox);
+  win->add(frame);
+
+  win->border_width(10);
+
+  ({cs,edit,edit2,hbox,vbox,frame})->show();
+  cs_changed(0,cs);
+  cs->signal_connect("destroy",_exit,0);
+  win->show();
+  return -1;
+}
diff --git a/src/post_modules/GTK/examples/low_level/psnow/psnow.pike b/src/post_modules/GTK/examples/low_level/psnow/psnow.pike
new file mode 100644
index 0000000000000000000000000000000000000000..02ce59dfeaa1a45533887c712a0adc537ea4bed2
--- /dev/null
+++ b/src/post_modules/GTK/examples/low_level/psnow/psnow.pike
@@ -0,0 +1,156 @@
+// This is a program that operates on a very low level. It draws
+// things in the root window.
+
+
+// The lack of comments is somewhat intentional.  Basically: Draw a
+// lot of snow falling on the background, more or less like the old
+// xsnow program.
+
+// This program is the only GTK program I have written that is not
+// event driven. There is not much GTK in here, though, this program
+// use almost exclusively GDK function calls. /per
+
+GDK.Window root;
+float mdx, mdy; // Size of the root window. 
+int windy, edx; // is it windy today? edx is the wind direction.
+
+#define I(X) Image.PNM.decode(Stdio.read_bytes("snow0" #X ".pbm"))->invert()
+
+array (GDK.GC) snow_flake_gcs = ({});
+array (Image.image) snow_flakes=({I(0), I(1), I(2),  I(3), I(4), I(5), I(6)});
+
+#define SPEED 1.0
+
+class Snowflake
+{
+  GDK.GC gc;
+  float x, y, dx, dy, dx2;
+  int ox, oy, xsize, ysize;
+
+  void init_flake()
+  {
+    x = (float)random(root->xsize()-8);
+    dx = (random(20)/(10.0*SPEED))-2.0;
+    dy = (random(90)/(10.0*SPEED))+0.5;
+    y = 0.0;
+    ox = oy = 0;
+  }
+
+  void step()
+  {
+    dx += (random(10)-4.5)/2.0*SPEED;
+    if(abs(dx) > 10.0) dx = 10.0*sgn(dx);
+    x += dx; y += dy;
+    if(windy)
+    {
+      if(windy > 100) dx2 += edx * 0.2;
+      else if(windy<=100) dx2 -= edx * 0.2;
+      x+=dx2;
+    }
+    int ix = (int)x;
+    int iy = (int)y;
+      
+    if(ix != ox || iy != oy)
+    {
+      if(y > mdy)
+        init_flake();
+      else if(x<0.0)
+        x = mdx;
+      else if(x>mdx)
+        x = 0.0;
+      root->clear( ox,oy, xsize, ysize );
+      ox = ix; oy = iy;
+      gc->set_clip_origin(ix,iy);
+      root->draw_rectangle(gc,1,ix,iy,xsize,ysize);
+    }
+    if( collided( this_object() ) )
+      init_flake();
+  }
+
+  void create()
+  {
+    int num = random(7);
+    xsize = snow_flakes[num]->xsize();  ysize = snow_flakes[num]->ysize();
+    gc = snow_flake_gcs[ num ];
+    init_flake();
+  }
+}
+
+array snow = ({});
+void make_some_snow()
+{
+  GDK.Color white = GDK.Color( 255,255,255 );
+  for(int i = 0; i<sizeof(snow_flakes); i++)
+  {
+    GDK.Bitmap b = GDK.Bitmap( snow_flakes[i] );
+    snow_flake_gcs += ({ GDK.GC( root ) });
+    snow_flake_gcs[i]->set_clip_mask( b );
+    snow_flake_gcs[i]->set_foreground( white );
+  }
+  snow = Array.map(allocate(50),Snowflake);
+}
+
+void move_snow()
+{
+  for(;;)
+  {  
+    if(!windy)
+    {
+      if(!random(1000))
+      {
+        windy = 200;
+        edx = (random(2)?-1:1);
+      }
+    } else
+      windy--;
+    snow->step();
+    GTK.flush();
+    sleep(0.025/SPEED);
+  }
+}
+
+GDK.Region region;
+
+int collided( Snowflake f )
+{
+  int x = (int)f->x, y = (int)f->y;
+  int w = (int)f->xsize;
+  int h = (int)f->ysize;
+  if( region->point_in( x, y+h ) || region->point_in( x+w, y+h ))
+  {
+    region |= GDK.Rectangle( x, y+h/2+h/4, w, h );
+    return 1;
+  }
+  return 0;
+}
+
+
+int main()
+{
+  GTK.setup_gtk();
+  root = GTK.root_window();
+  region = GDK.Region();
+
+
+  // Is there any 'fake' root windows out there to draw the snow in?
+  array(mapping) maybe
+    =root->children()->get_property(GDK.Atom.__SWM_VROOT)-({0});
+  if(sizeof(maybe))
+      root = GDK.Window( maybe[0]->data[0] );
+
+  mapping rg = root->get_geometry();
+  foreach( root->children(), object o )
+  {
+    if(o->is_visible())
+    {
+      mapping g = o->get_geometry();
+      if(g->width == rg->width)
+        continue;
+      region |= GDK.Rectangle( g->x, g->y, g->width, g->height );
+    }
+  }
+  region |= GDK.Rectangle( 0, rg->height-1, rg->width, 1 );
+  mdx = (float)root->xsize(); mdy = (float)root->ysize();
+  make_some_snow();
+  move_snow();
+}
diff --git a/src/post_modules/GTK/examples/low_level/psnow/snow00.pbm b/src/post_modules/GTK/examples/low_level/psnow/snow00.pbm
new file mode 100644
index 0000000000000000000000000000000000000000..5d7fa1ee2b50b21789bc9a08834b1402b241fc0c
Binary files /dev/null and b/src/post_modules/GTK/examples/low_level/psnow/snow00.pbm differ
diff --git a/src/post_modules/GTK/examples/low_level/psnow/snow01.pbm b/src/post_modules/GTK/examples/low_level/psnow/snow01.pbm
new file mode 100644
index 0000000000000000000000000000000000000000..994e7240ec3b3bcc4deee4663a5bb50a6f2305ca
Binary files /dev/null and b/src/post_modules/GTK/examples/low_level/psnow/snow01.pbm differ
diff --git a/src/post_modules/GTK/examples/low_level/psnow/snow02.pbm b/src/post_modules/GTK/examples/low_level/psnow/snow02.pbm
new file mode 100644
index 0000000000000000000000000000000000000000..77a5c2e84daf4ba74f2207227106faf70db6d048
Binary files /dev/null and b/src/post_modules/GTK/examples/low_level/psnow/snow02.pbm differ
diff --git a/src/post_modules/GTK/examples/low_level/psnow/snow03.pbm b/src/post_modules/GTK/examples/low_level/psnow/snow03.pbm
new file mode 100644
index 0000000000000000000000000000000000000000..77a5c2e84daf4ba74f2207227106faf70db6d048
Binary files /dev/null and b/src/post_modules/GTK/examples/low_level/psnow/snow03.pbm differ
diff --git a/src/post_modules/GTK/examples/low_level/psnow/snow04.pbm b/src/post_modules/GTK/examples/low_level/psnow/snow04.pbm
new file mode 100644
index 0000000000000000000000000000000000000000..994e7240ec3b3bcc4deee4663a5bb50a6f2305ca
Binary files /dev/null and b/src/post_modules/GTK/examples/low_level/psnow/snow04.pbm differ
diff --git a/src/post_modules/GTK/examples/low_level/psnow/snow05.pbm b/src/post_modules/GTK/examples/low_level/psnow/snow05.pbm
new file mode 100644
index 0000000000000000000000000000000000000000..77a5c2e84daf4ba74f2207227106faf70db6d048
Binary files /dev/null and b/src/post_modules/GTK/examples/low_level/psnow/snow05.pbm differ
diff --git a/src/post_modules/GTK/examples/low_level/psnow/snow06.pbm b/src/post_modules/GTK/examples/low_level/psnow/snow06.pbm
new file mode 100644
index 0000000000000000000000000000000000000000..5d7fa1ee2b50b21789bc9a08834b1402b241fc0c
Binary files /dev/null and b/src/post_modules/GTK/examples/low_level/psnow/snow06.pbm differ
diff --git a/src/post_modules/GTK/examples/pv b/src/post_modules/GTK/examples/pv
new file mode 100755
index 0000000000000000000000000000000000000000..9cfefca04116d4fcab8ed6fd0dabd55f1e0b47b8
--- /dev/null
+++ b/src/post_modules/GTK/examples/pv
@@ -0,0 +1,426 @@
+#!/usr/local/bin/pike
+// -*- pike -*-
+
+
+object root()
+{
+  GDK.Window root = GTK.root_window();
+  array maybe=root->children()->get_property(GDK.Atom.__SWM_VROOT)-({0});
+  if(sizeof(maybe)) root=GDK.Window( maybe[0]->data[0] );
+  return root;
+}
+
+array(int) get_max_size( Image.image q)
+{
+  return ({
+    min( q->xsize(), 
+         root()->xsize()-30  ),
+    min( q->ysize(), 
+         root()->ysize()-30  )
+  });
+          
+}
+
+
+class ImageWindow
+{
+  inherit GTK.Image;
+  GDK.Image pix;
+  mapping _img;
+
+  float scale = 1.0;
+
+  void create()
+  {
+    ::create( pix = GDK.Image( 1 )->set(100,100));
+  }
+
+  string pct( float what )
+  {
+    return sprintf("%3d%%", (int)(what*100));
+  }
+
+  void set_image( mapping img )
+  {
+    object alpha;
+    _img = copy_value(img);
+    
+    if( scale != 1.0 )
+    {
+      if( img->alpha )
+        img->alpha = img->alpha->scale( scale );
+      img->img = img->img->scale( scale );
+    }
+
+    if( img->alpha )
+    {
+      alpha = Image.Image( img->img->xsize(),
+                           img->img->ysize(),
+                           120,120,120 );
+      alpha->setcolor( 159,159,159 );
+
+#define STEP 30
+      for(int x=0; x<img->img->xsize(); x+=STEP )
+        for(int y=0; y<img->img->ysize(); y+=STEP*2 )
+          alpha->box( x, y+(x/STEP%2)*STEP, x+(STEP-1), y+(x/STEP%2)*STEP+(STEP-1) );
+      alpha->paste_mask( img->img, img->alpha );
+      img->img = alpha;
+      img->alpha = 0;
+      alpha = 0;
+    }
+
+
+    object r = parent();
+    while( r->parent() )
+      r = r->parent();
+    int x, y;
+    [x,y] = get_max_size( img->img );
+    r->set_usize( x,y );
+
+    if( x != img->img->xsize() || y != img->img->ysize())
+      r->child()->set_policy( GTK.PolicyAlways,GTK.PolicyAlways );
+    else
+      r->child()->set_policy( GTK.PolicyNever,GTK.PolicyNever );
+    r->set_title("PV: "+img->img_name+" "+img->img->xsize()+"x"+
+                 img->img->ysize()+" "+img->format+ " ("+pct( scale )+")" );
+
+
+    pix->set( img->img );
+    set( pix );
+  }
+
+
+
+
+  void scale_image( float to )
+  {
+    if( !to )
+      scale = 1.0;
+    else
+      scale *= to;
+    set_image( _img );
+  }
+
+  ImageWindow load_image( string img )
+  {
+    mapping q = cload_img( img );
+//     scale = 1.0;
+    if( !q || !q->img )
+    {
+      int x, y;
+      int xp, yp;
+      q = ([
+        "img":Image.Image(400,200),
+        "alpha":Image.Image(400,200),
+        "format":"internal"
+      ]);
+      object fnt = Image.Font();
+      fnt->center();
+      object txt = fnt->write("Failed to load image",img,"Sorry.")->scale(1.5);
+
+     preload_image( replace( __FILE__, "pv", "unknown.xcf.gz" ) );
+     xp = q->img->xsize()-preloaded_image_data->img->xsize();
+     yp = q->img->ysize()-preloaded_image_data->img->ysize();
+
+     q->img_name = img;
+     q->img->paste_mask(preloaded_image_data->img,preloaded_image_data->alpha,
+                        xp, yp);
+     q->alpha->paste_alpha_color( preloaded_image_data->alpha, 255,255,255, 
+                                 xp, yp);
+
+
+      xp = q->img->xsize()/2 - txt->xsize()/2;
+      yp = 20;
+      for( x = xp-1; x<xp+2; x++ )
+        for( y = yp-1; y<yp+2; y++ )
+          q->alpha->paste_alpha_color( txt, 255,255,255, x,y );
+      q->img->paste_alpha_color( txt,255,255,0,xp,yp );
+     
+    }
+
+    set_image( q );
+    queue_resize();
+    return this_object();
+  }
+}
+
+
+mapping preloaded_image_data;
+string preloaded_image;
+
+mapping options;
+
+void preload_image( string img )
+{
+  if(preloaded_image == img )
+    return;
+  preloaded_image = preloaded_image_data = 0;
+  preloaded_image_data = GTK.Util.low_load_image( img,options );
+  preloaded_image = img;
+}
+
+mapping cload_img( string img )
+{
+  mapping res;
+  if( img == preloaded_image )
+  {
+    res = preloaded_image_data;
+    if( next_image( img ) != img )
+    {
+      remove_call_out( preload_image );
+      call_out( preload_image, 0.1, next_image( img ) );
+    }
+    if( preloaded_image_data )
+      preloaded_image_data->img_name = img;
+    return preloaded_image_data;
+  }
+  remove_call_out( preload_image );
+  preload_image( img );
+  return cload_img( img );
+}
+
+array images;
+int current_image;
+
+string next_image( string img )
+{
+  int pos = search( images, img );
+  if( sizeof( images ) > pos+1 )
+    return images[pos+1];
+  return images[0];
+}
+
+class CLib
+{
+  int convert( mapping data, function cont );
+}
+
+
+
+string copy_to, default_copy_encode_format;
+CLib copy_library;
+
+class doCopy
+{
+  mapping data = ([]);
+
+  void output()
+  {
+    Stdio.File out = Stdio.File( );
+    if( !out->open( data->to, "wct" ) )
+      werror("Open of "+data->to+" for destination failed.\n");
+    if( data->outdata )
+      out->write( data->outdata );
+    else if( data->outfmt )
+    {
+      data->mask = data->alpha;
+      if(catch(out->write(Image[upper_case( data->outfmt )]
+                          ->encode( data->i, data->img ))))
+        out->write(Image[upper_case( data->outfmt )]->encode( data->i ));
+    } else {
+      out->write( Image.PNG.encode( data->i, data->img ) );
+    }
+  }
+
+  void create( string file )
+  {
+    data->img = GTK.Util.low_load_image( file );
+    data->i = data->img->img;
+    data->from = file;
+    data->to = copy_to + (file - dirname( file ) );
+    data->outfmt = default_copy_encode_format;
+    
+    if( copy_library )
+      switch( copy_library->convert( data, output ) )
+      {
+       case 1:
+         destruct();
+         return;
+       case -1:
+         return;
+      }
+
+    output();
+    destruct();
+    return;
+  }
+}
+
+ImageWindow imgwin;
+
+void key_pressed( object w, object win, mixed e )
+{
+  switch(e->data) 
+  {
+   case "<": imgwin->scale_image( 0.5 );  break;
+   case ">": imgwin->scale_image( 2.0 );  break;
+   case ",": imgwin->scale_image( 0.9 );  break;
+   case ".": imgwin->scale_image( 1.1 );  break;
+   case "n": imgwin->scale_image( 0   );  break;
+   case "s":
+     break;
+   case "D":
+     rm( images[ current_image ] );
+     break;
+   case "q":
+     exit(0);
+   case "c":
+     if( copy_to )
+       doCopy( images[ current_image ] );
+     break;
+   case " ":
+     current_image+=2;
+   case "\b":
+     current_image--;
+     current_image = current_image % sizeof( images );
+     w->load_image( images[ current_image ] );
+     break;
+  }
+}
+
+int main(int argc, array argv)
+{
+  images = ({});
+  options = ([ ]);
+  int all_images;
+  foreach( argv[1..], string i )
+  {
+    if( !all_images )
+      switch( i )
+      {
+       case "--name-layers":
+         options->mark_layer_names = Image.Font();
+         continue;
+       case "--mark-layers":
+         options->mark_layers = 1;
+         continue;
+       case "--mark-active":
+         options->mark_active_layer = 1;
+         continue;
+       case "--mark-selection":
+         options->draw_selection = 1;
+         continue;
+       case "--mark-guides":
+         options->draw_guides = 1;
+         continue;
+       case "--draw-all-layers":
+         options->draw_all_layers = 1;
+         continue;
+
+       case "--help":
+         werror("%s [arguments] file(s)\n"
+               " General options:\n"
+               "  --help              This information\n"
+               "  --copy-to=dir       Bind the 'c' key to copy the current\n"
+               "                      image to 'dir'\n"
+               "  --copy-conv=conv    Convert the image while copying.\n"
+               "                      Default is no conversion.\n"
+               "                      Supported formats:\n"
+               "                       jpeg, gif, png, bmp, pcx, tga, ilbm\n"
+               "                       tiff, xpm, xbm, avs, gd, hrz, pnm\n"
+               "                       ps\n"
+               "  --copy-conv-code=pike\n"
+               "                      Apply the pike code in pike while\n"
+               "                      copying. The image is in 'i', the\n"
+               "                      source file name is in 'src', the\n"
+               "                      destination filename is in 'dest',\n"
+               "                      metadata (like alpha channel) is in\n"
+               "                      the 'img' mapping. Encoding format is\n"
+               "                      in the variable 'outfmt', if 'outdata'\n"
+               "                      is set, this is the data that will be\n"
+               "                      written to the destination file.\n" 
+               "                      Example:\n"
+               "                        'i = i->scale(2.0); rm(src);'\n\n"
+               "  --copy-conv-library=file\n"
+               "                      As above, but the variables are in a\n"
+               "                      mapping passed to the 'convert'\n"
+               "                      function in the specified file.\n"
+               "                      If you return 1, no copying will\n"
+               "                      be done, you can use GTK functions\n"
+               "                      from here.\n"
+               "                      If you return -1, the copy will be\n"
+               "                      postponed. Call the second argument\n"
+               "                      you got to the 'convert' function to\n"
+               "                      finish the copying.\n\n"
+               " XCF specific options:\n"
+               "  --name-layers       Print the name of the layers\n"
+               "  --mark-layers       Draw a border around the layers\n"
+               "  --mark-active       Draw a border around the active layer\n"
+               "  --mark-selection    Draw the selection\n"
+               "  --mark-guides       Draw the guides\n"
+               "  --draw-all-layers   Include all layers, even those marked\n"
+               "                      as invisible\n"
+                ,argv[0]);
+         exit(0);
+       default:
+         string a, b;
+         if( i == "--" ) {
+           all_images = 1;
+           continue;
+         }
+         if( sscanf( i, "--%s=%s", a, b )  == 2)
+         {
+           switch( a )
+           {
+            case "copy-conv-library":
+              if( catch {
+                copy_library = compile_file( b )();
+              }) 
+                exit(1);
+              continue;
+            case "copy-conv-code":
+              if( catch {
+                copy_library = compile_string(
+"  int convert( mapping what, function f ){ "
+"    string from = what->from; "
+"    string to   = what->to; "
+"    mapping img = what->img; "
+"    object i = what->i; "
+"    object outfmt = what->outfmt; "
+"    string outdata; do {" +  b + ";}while(0);\n"
+"   what->img = img;\n"
+"   what->i = i;\n"
+"   what->to = to;\n"
+"   what->outfmt = outfmt;\n"
+"   what->outdata = outdata;\n}")();
+              })
+                exit(1);
+              continue;
+            case "copy-to":
+              copy_to = b;
+              continue;
+            case "copy-conv":
+              default_copy_encode_format = b;
+              continue;
+            default:
+              werror("Unknown argument: --"+a+"\n");
+              exit(1);
+           }
+         }
+         if( sscanf( i, "--%s", a ))
+         {
+           werror("Unknown argument: --"+a+"\n");
+           exit(1);
+         }
+      }
+    images += ({ i });
+  }
+  argv = GTK.setup_gtk( argv )[1..];
+  
+
+
+  object w,win =  GTK.Window( GTK.WindowToplevel );
+
+  object win2 = GTK.ScrolledWindow( 0,0 )->
+         set_policy( GTK.PolicyNever, GTK.PolicyNever );
+
+  win->signal_connect( "destroy", _exit, 0 );
+  imgwin = w = ImageWindow( );
+  win2->add( w->show() );
+  win->add( win2->show() );
+  w->load_image( images[0] )->show();
+  win->signal_connect( "key_press_event", key_pressed, w );
+  win->set_policy( 0,0,1 );
+  win->show();
+  return -1;
+}
diff --git a/src/post_modules/GTK/examples/simple_menu.pike b/src/post_modules/GTK/examples/simple_menu.pike
new file mode 100644
index 0000000000000000000000000000000000000000..52b67ae75b791d09f85932188af39d7df1f0148e
--- /dev/null
+++ b/src/post_modules/GTK/examples/simple_menu.pike
@@ -0,0 +1,40 @@
+import GTK.MenuFactory;
+
+// Display a simple menu, and handle saving and loading of shortcuts.
+// 
+
+int main()
+{
+  GTK.setup_gtk( "simple menu" );
+  GTK.Window win = GTK.Window( GTK.WindowToplevel );
+
+  mapping sc = GTK.Util.parse_shortcut_file( "simple_menu_shortcuts" );
+
+  array defs = ({
+    MenuDef( "File/Load...", 0, 0 ),
+    MenuDef( "File/Save...", 0, 0 ),
+    MenuDef( "File/<separator>", 0, 0 ),
+    MenuDef( "File/Quit...", _exit, 0 ),
+
+    MenuDef( "Misc/number 1", 0, 0 ),
+    MenuDef( "Misc/number 2", 0, 0 ),
+    MenuDef( "Misc/<separator>", 0, 0 ),
+    MenuDef( "Misc/Number 3/Number 1", 0, 0 ),
+    MenuDef( "Misc/Number 3/Number 2", 0, 0 ),
+    MenuDef( "Misc/Number 3/Number 3", 0, 0 ),
+  });
+
+  foreach(defs, object o) 
+    if(sc[o->menu_path])
+      o->assign_shortcut( sc[o->menu_path] );
+
+  set_menubar_modify_callback( lambda(mapping m) {
+          GTK.Util.save_shortcut_file( "simple_menu_shortcuts", m );
+     });  
+  [object bar,object map] = MenuFactory(@defs);
+  set_menubar_modify_callback( 0 );  
+  
+  win->add_accel_group( map );
+  win->add( bar->show() )->show();
+  return -1;
+}
diff --git a/src/post_modules/GTK/examples/simple_menu_shortcuts b/src/post_modules/GTK/examples/simple_menu_shortcuts
new file mode 100644
index 0000000000000000000000000000000000000000..0789e0ce7765f6f661b806a6198ff145ec634322
--- /dev/null
+++ b/src/post_modules/GTK/examples/simple_menu_shortcuts
@@ -0,0 +1,4 @@
+"File/Load..." "A-l"
+"File/Quit..." "A-q"
+"File/Save..." "A-s"
+"Misc/number 1" "C-1"
diff --git a/src/post_modules/GTK/examples/testdnd.pike b/src/post_modules/GTK/examples/testdnd.pike
new file mode 100644
index 0000000000000000000000000000000000000000..f3740747ca5b82d26dbc28bc53bd77341189c3ad
--- /dev/null
+++ b/src/post_modules/GTK/examples/testdnd.pike
@@ -0,0 +1,52 @@
+void drag_data_get( int q, object w, mixed context, 
+                    object selection, int a, int b)
+{
+  selection->set("Some data for the drop to receive\n");
+}
+
+void drag_data_received( int q, object w, mixed context,
+                         int x, int y, object selection, 
+                         int type, int time )
+{
+  werror("got DND type %s\nData is %s\n",
+	 selection->type()->get_name(),
+	 selection->data());
+}
+
+int main(int argc, array argv)
+{
+  GTK.setup_gtk(argv);
+
+  object drag_icon = GDK.Pixmap( Image.image( 64,64 )->test() );
+
+  object window = GTK.Window( GTK.WindowToplevel );
+  window->signal_connect( "destroy", exit, 0 );
+  object table = GTK.Hbox( 0,0 );
+  window->add( table );
+
+  object to = GTK.Button("Drop here!");
+  object from = GTK.Button("Drag here!");
+  
+  to->drag_dest_set( GTK.DestDefaultAll, ({
+                      ({ "STRING", 0, 0 }),
+                      ({ "text/plain", 0, 0 }),
+                     }),
+		     GDK.ActionCopy|GDK.ActionMove|GDK.ActionDefault|
+		     GDK.ActionLink|GDK.ActionPrivate|GDK.ActionAsk);
+
+  to->signal_connect( "drag_data_received", drag_data_received );
+
+  from->drag_source_set( GDK.Button1Mask|GDK.Button2Mask,
+                         ({ ({ "STRING", 0, 0 }),
+                            ({ "text/plain", 0, 0 }),
+                            ({ "application/x-rootwin-drop", 0, 1 }),
+                         }),
+                         GDK.ActionCopy|GDK.ActionMove );
+  from->drag_source_set_icon( drag_icon, 0 );
+  from->signal_connect( "drag_data_get", drag_data_get );
+
+  table->add( from );
+  table->add( to );
+  window->show_all();
+  return -1;
+}
diff --git a/src/post_modules/GTK/make_example_image.pike b/src/post_modules/GTK/make_example_image.pike
new file mode 100644
index 0000000000000000000000000000000000000000..0de47f425e7681395c16725dc33210afa2e5b977
--- /dev/null
+++ b/src/post_modules/GTK/make_example_image.pike
@@ -0,0 +1,144 @@
+function write;
+
+object get_widget_from( string what )
+{
+  array err;
+  mixed res;
+  err = catch {
+    res= compile_string( "object foo(){ return "+what+"; }")()->foo();
+  };
+  if(!res)
+    werror("Error while compiling or running "+what+"\n: %s\n", err?err[0]:"No return value");
+  return res;
+}
+
+string file_name(string from)
+{
+  return ((MIME.encode_base64((Crypto.md5()->update(from)->
+			       digest()),1)-"=")-"/")[..40]
+    +".gif";
+}
+
+object ex;
+string source;
+int start_indent;
+array(int) istack = ({});
+
+void push_indent()
+{
+  istack += ({ start_indent });
+}
+
+void pop_indent()
+{
+  if(sizeof(istack)) start_indent = istack[-1];
+  istack = istack[..sizeof(istack)-2];
+}
+
+string indent(string what, int|void limit)
+{
+  if(!limit) limit=40;
+  string res="";
+  string line="";
+  int nobr;
+  for(int i=0;i<strlen(what); i++)
+  {
+    line += what[i..i];
+    switch(what[i])
+    {
+     case '(': push_indent(); start_indent=strlen(line); break;
+     case '"': nobr = !nobr; break;
+     case ')': pop_indent(); if(!(strlen(what)>i+1 && what[i+1]=='-')) break;
+     case '}': pop_indent(); res += line+"\n"; line=" "*start_indent; break;
+     case '{': push_indent(); start_indent += 2;
+     case ';': res += line+"\n"; line=" "*start_indent; break;
+     case ' ':
+     case ',':
+     case '>':
+       if(!nobr)
+       {
+	 if(strlen(line) >= limit) 
+	 {
+	   if(strlen(line) > limit)
+	   {
+	     if(limit < 50) limit=strlen(line);
+	   }
+	   res += line+"\n";
+	   line = " "*start_indent;
+	 }
+       }
+    }
+  }
+  return res+line;
+}
+
+string tags(string source)
+{
+  return ("<table cellpadding=1 bgcolor=black><tr><td><table bgcolor=#e0e0e0 cellpadding=8 cellspacing=0 border=0><tr><td><img src="+file_name(source)+">"
+	"</td></td><tr><td><font size=-1><pre>"+
+	replace(indent(source), ({"<",">","&"}), ({"&lt;", "&gt;", "&amp;"}))+
+	"</pre></font></td></tr></table></td></tr></table>");
+}
+
+void grab(object w)
+{
+  object i = GTK.GdkImage();
+  if(w->xsize() == 40 || w->ysize() == 40 )
+  {
+    werror("Image dimensions are 0x0!\n");
+    exit(1);
+  }
+  i->grab( w, 20,20, w->xsize()-40, w->ysize()-40);
+  object i = Image.PNM.decode( i->get_pnm() );
+
+  mkdir("docs");
+  rm("docs/"+file_name(source));
+  function fun;
+#if constant(Image.GIF.encode)
+  Stdio.write_file("docs/"+file_name(source), Image.GIF.encode(i));
+#else
+  Stdio.write_file("docs/"+file_name(source), i->togif_fs());
+#endif
+  write(tags( source ));
+  
+  exit(0);
+}
+
+void got_event( int q, object w, mapping  e )
+{
+  if(e->type == "expose" )
+    call_out(grab, 0.01, w );
+}
+
+void show_recursively(object w)
+{
+  if(w->children)
+    Array.map( w->children(), show_recursively );
+  w->show();
+}
+
+int main(int argc, array (string) argv)
+{
+  object w;
+  if(!write) write = Stdio.stdout->write;
+  source = argv[1];
+  if(file_stat( "docs/"+file_name(argv[1])))
+  {
+    write(tags(argv[1]));
+    exit(0);
+  }
+  GTK.setup_gtk( "make_gtkexample", 1 );
+  if(argc == 2)
+  {
+    w = GTK.Window( GTK.WINDOW_TOPLEVEL );
+    w->set_title("Example image generation");
+    w->add( ex=get_widget_from( argv[1] ) );
+    w->set_border_width(20);
+  } else {
+    w = get_widget_from( argv[1] );
+    w->set_border_width(20);
+  }
+  show_recursively( w );
+  w->signal_connect( "event", got_event );
+  return -1;
+}
diff --git a/src/post_modules/GTK/make_sources.pike b/src/post_modules/GTK/make_sources.pike
new file mode 100644
index 0000000000000000000000000000000000000000..2393da62cd75ee3e318fe929108d89c3b678b957
--- /dev/null
+++ b/src/post_modules/GTK/make_sources.pike
@@ -0,0 +1,16 @@
+void main(int argc, array argv)
+{
+  string dest = getcwd();
+  if(!cd(argv[1]))
+  {
+    werror("*** Cannot CD to "+argv[1]+"\n");
+    exit(1);
+  }
+  string s = "";
+  foreach(get_dir("."), string f)
+  {
+    if(f[0] != '.' && f[0] != '#' && f[-1] != '~' && Stdio.file_size(f)>0)
+      s += "source/"+f+" ";
+  }
+  Stdio.File(dest+"/sources", "wct")->write( s[..strlen(s)-2] );
+}
diff --git a/src/post_modules/GTK/module.pmod.in b/src/post_modules/GTK/module.pmod.in
new file mode 100644
index 0000000000000000000000000000000000000000..37d325dab4cd652c7d0af076475e1e8f22a85099
--- /dev/null
+++ b/src/post_modules/GTK/module.pmod.in
@@ -0,0 +1,59 @@
+inherit @module@;
+
+#define INDEX(x) predef::`->(this_object(),(x))
+
+string unsillycaps(string what)
+{
+  string res=upper_case(what[0..0]);
+  foreach(what[1..]/"", string q)
+    if(lower_case(q)==q)
+      res += q;
+    else
+      res += "_"+lower_case(q);
+  return res;
+}
+
+array setup_gtk(array|string|void name, int|void norc)
+{
+  array res;
+  if(stringp(name))
+    name = ({ name });
+  if(name)
+    res = ::setup_gtk(name);
+  else
+    res = ::setup_gtk();
+  if(!norc)
+  {
+    if(file_stat( getenv("HOME")+"/.pgtkrc" ))
+      parse_rc( cpp(Stdio.read_bytes(getenv("HOME")+"/.pgtkrc")) ||"");
+    else if(file_stat( getenv("HOME")+"/.gtkrc" ))
+      parse_rc( Stdio.read_bytes(getenv("HOME")+"/.gtkrc") );
+  }
+  return res;
+}
+
+mixed `[](string what)
+{
+  if(what == "destroy")
+    if(sizeof(backtrace())>2)
+    {
+      werror(describe_backtrace(backtrace()));
+      return s_destroy;
+    }
+    else
+     return ([])[0];
+
+  if(what == "_module_value") return ([])[0];
+
+  if(!zero_type(INDEX(what)))
+    return INDEX(what);
+  if(!zero_type(INDEX("s_"+what)))
+    return INDEX("s_"+what);
+  if(!zero_type(INDEX(upper_case(what))))
+    return INDEX(upper_case(what));
+  if(!zero_type(INDEX(unsillycaps(what))))
+    return INDEX(unsillycaps(what));
+  if(!zero_type(INDEX(upper_case(unsillycaps(what)))))
+    return INDEX(upper_case(unsillycaps(what)));
+  return  GTKSupport[what];
+}
diff --git a/src/post_modules/GTK/options.in b/src/post_modules/GTK/options.in
new file mode 100644
index 0000000000000000000000000000000000000000..bb277648f0d870e8a1f53c0aa6ea80fc550107e6
--- /dev/null
+++ b/src/post_modules/GTK/options.in
@@ -0,0 +1,2 @@
+@pgtk_has_sheet@
+@pgtk_has_glarea@
diff --git a/src/post_modules/GTK/pcdocs/Alert b/src/post_modules/GTK/pcdocs/Alert
new file mode 100644
index 0000000000000000000000000000000000000000..fa4a633b31bc3ceae855acdd903205e2d451fbb1
--- /dev/null
+++ b/src/post_modules/GTK/pcdocs/Alert
@@ -0,0 +1,9 @@
+PROGRAM(alert);
+INHERIT(dialog);
+FUNCTION(create, "function(string,string:void)");
+NAME_ARGS(contents, title);
+// Create a simple alert window. The default title is 'Alert'.
+// A single button 'Ok' will be created. Pressing it removes the dialog.
+
+FUNCTION(ok, "function(void:GTK.Button)");
+// Returns the ok button
diff --git a/src/post_modules/GTK/pcdocs/MenuFactory b/src/post_modules/GTK/pcdocs/MenuFactory
new file mode 100644
index 0000000000000000000000000000000000000000..56c21e5e7c381204785569c97d90d58cd2553e60
--- /dev/null
+++ b/src/post_modules/GTK/pcdocs/MenuFactory
@@ -0,0 +1,103 @@
+PROGRAM(MenuFactory);
+FUNCTION(set_menubar_modify_callback, "function(function:void)");
+NAME_ARGS(callback);
+// The function passed as the argument to this function will be called
+// each time the accelerator key mapping is changed by the user with
+// the new mapping as the argument.<p>
+//  <b>NOTE</b>: This function is only used when the menubar
+//  is created, once you are done with the menubar creation, the
+//  callbacks for that menubar will be fixed.
+
+FUNCTION(get_menubar_mapping, "function(void:mapping)");
+//  Returns a (flat) mapping ([ path:GTK.MenuItem ]).<p>
+// <b>NOTE:</b> This function can only be called <i>after</i> the menubar is created.
+
+FUNCTION(MenyFactory, "function(array,MenuDef ...:void)");
+NAME_ARGS(items);
+// Returns ({ GTK.MenuBar, GTK.AcceleratorTable })
+// <p>
+// This is the function that actually builds the menubar.
+// A short example:
+//<p><pre>
+// import GTK.MenuFactory;
+// [GTK.MenuBar bar, GTK.AcceleratorTable map] = 
+//  MenuFactory( 
+//    MenuDef( "File/New", new_file, 0, "A-N" ), 
+//    MenuDef( "File/Open", new_file, 1, "A-O" ), 
+//    MenuDef( "File/Save", save_file, 0, "A-S" ), 
+//    MenuDef( "File/<separator>", 0, 0 ),
+//    MenuDef( "File/Quit", _exit, 0, "A-Q" ), 
+//  );
+//</pre>
+
+// A single menu entry.
+FUNCTION(MenuDef, "function(string,function|void,mixed|void,string|void,int|void)");
+NAME_ARGS(path,callback,callbackargument,shortcut,flags);
+RETURNS(MenuDef);
+// Path is the menupath. A submenu will be created for each
+// "Directory" in the path, and menuitems will be created for the
+// "files". There are two special cases: The "file" '<separator>' will
+// create a thin line. The "file"prefix <check> will make the menuitem
+// a checkmenuitem instead of a normal menuitem.
+//<p>
+
+// The second and third arguments are the callback function and the
+// first callback function argument. If the callback function argument
+// is an array, the indices of the array will be pushed as
+// arguments. To call the function with an array as the only argument,
+// make an array with the array in.  The callback function will be
+// called like callback( arg, widget ), or if arg is an array,
+// callback( arg[0], arg[1], ..., widget )
+//<p>
+// The fourth argument, shortcut, is the shortcut to bind to this menu
+// item. The shortcut can be changed later on by calling
+// assign_shortcut, or by the user by pressing the desired
+// keycombination over the menu item.
+// <p>The shortcut syntax is:
+// m[m[..]]-key, where m is one or more modifier character, and key is
+// the desired key (<b>NOTE</b>: Key must be in the range 0-255
+// currently, this will hopefully be fixed by the GTK people in the
+// future)
+// <p>
+// The modifiers are:<p><pre>
+// s: Shift
+// c: Control
+// a: Modifier 1 (called alt by the GTK people, that's not true, though)
+// 1: Modifier 1
+// g: Modifier 2 (called altgr by the GTK people, that's not true, though)
+// 2: Modifier 2
+// m: Modifier 3 (not mapped by the GTK people, meta on _my_ keyboard)
+// 3: Modifier 3
+// h: Modifier 4 (not mapped by the GTK people, hyper on _my_ keyboard)
+// 4: Modifier 4
+// u: Modifier 5 (not mapped by the GTK people, super on _my_ keyboard)
+// 5: Modifier 5
+// </pre>
+// <p>
+// The last argument (flags) is currently ignored.
+
+FUNCTION(MenuDef->assign_shortcut, new_shortcut);
+NAME_ARGS(new_shortcut);
+// Set a new shortcut as the current one.
+// 
+// <p>
+// The shortcut syntax is:
+// m[m[..]]-key, where m is one or more modifier character, and key is
+// the desired key (<b>NOTE</b>: Key must be in the range 0-255
+// currently, this will hopefully be fixed by the GTK people in the
+// future)
+// <p>
+// The modifiers are:<p><pre>
+// s: Shift
+// c: Control
+// a: Modifier 1 (called alt by the GTK people, that's not true, though)
+// 1: Modifier 1
+// g: Modifier 2 (called altgr by the GTK people, that's not true, though)
+// 2: Modifier 2
+// m: Modifier 3 (not mapped by the GTK people, meta on _my_ keyboard)
+// 3: Modifier 3
+// h: Modifier 4 (not mapped by the GTK people, hyper on _my_ keyboard)
+// 4: Modifier 4
+// u: Modifier 5 (not mapped by the GTK people, super on _my_ keyboard)
+// 5: Modifier 5
+// </pre>
diff --git a/src/post_modules/GTK/pcdocs/SClist b/src/post_modules/GTK/pcdocs/SClist
new file mode 100644
index 0000000000000000000000000000000000000000..0ec3deb8ba7151691ca0a5e6fd4bcaaf8bbfdc0d
--- /dev/null
+++ b/src/post_modules/GTK/pcdocs/SClist
@@ -0,0 +1,10 @@
+PROGRAM(SClist); 
+INHERIT(clist); 
+// A Clist with scrollbars. 
+FUNCTION(set_policy, "function(int,int:object)");
+NAME_ARGS(hpolicy,vpolicy);
+// One of CONST(GTK_POLICY)
+FUNCTION(create, "function(int:object)");
+NAME_ARGS(ncolumns);
+RETURNS(GTK.SClist);
+// Create a new SClist
\ No newline at end of file
diff --git a/src/post_modules/GTK/pcdocs/pDrawingArea b/src/post_modules/GTK/pcdocs/pDrawingArea
new file mode 100644
index 0000000000000000000000000000000000000000..bb8707f344b5b10d77815cb800211cbf9e07ff4f
--- /dev/null
+++ b/src/post_modules/GTK/pcdocs/pDrawingArea
@@ -0,0 +1,9 @@
+PROGRAM(pDrawingArea); 
+INHERIT(drawing_area); 
+// A Drawing area with backing store. Basically, the only difference
+// from a drawing area widget is that this one never loose it's
+// contents unless you do paint over them.
+// <p>
+// It also use quite a significant amount of memory if the backing
+// pixmap has many bitplanes, and the drawing area is large.
+
diff --git a/src/post_modules/GTK/pgtk.c.head b/src/post_modules/GTK/pgtk.c.head
new file mode 100644
index 0000000000000000000000000000000000000000..d7cc011ba1439a96a34d8d2aa39a624db029c1d0
--- /dev/null
+++ b/src/post_modules/GTK/pgtk.c.head
@@ -0,0 +1,27 @@
+/* This is very much -*- c -*- code */
+#include "config.h"
+#include <gtk/gtk.h>
+#include <gdk/gdkx.h>
+#include <program.h>
+#include <pike_types.h>
+#include <interpret.h>
+#include <module_support.h>
+#include <error.h>
+#include <array.h>
+#include <backend.h>
+#include <stralloc.h>
+#include <mapping.h>
+#include <object.h>
+#include <threads.h>
+#include <builtin_functions.h>
+#include <operators.h>
+#include "prototypes.h"
+#ifdef HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#ifdef HAVE_ARPA_INET_H
+#include <arpa/inet.h>
+#endif
+
+#include "pgtk.h"
+PROTOTYPES
diff --git a/src/post_modules/GTK/pgtk.h b/src/post_modules/GTK/pgtk.h
new file mode 100644
index 0000000000000000000000000000000000000000..c8150a9ec2162d14a8b8613ece80fb6c1c453c8d
--- /dev/null
+++ b/src/post_modules/GTK/pgtk.h
@@ -0,0 +1,92 @@
+struct object_wrapper 
+{
+  GtkObject *obj;
+  int extra_int;
+  void *extra_data;
+};
+
+
+struct signal_data
+{
+  struct svalue cb;
+  struct svalue args;
+};
+
+struct my_pixel 
+{
+  unsigned char r;
+  unsigned char g;
+  unsigned char b;
+};
+
+extern int pigtk_is_setup;
+
+int get_color_from_pikecolor( struct object *o, int *r, int *g, int *b );
+
+int pgtk_signal_func_wrapper(GtkObject *obj,struct signal_data *d,
+                             int nparams, GtkArg *params);
+void pgtk_free_signal_data( struct signal_data *s);
+
+void push_gdk_event(GdkEvent *e);
+
+int pgtkbuttonfuncwrapper(GtkObject *obj, struct signal_data *d,  void *foo);
+void *get_swapped_string(struct pike_string *s, int force_wide);
+int signal_func_wrapper(GtkObject *obj, struct signal_data *d, 
+                        int nparams, GtkArg *params);
+
+#define pgtk__init_this_object() pgtk__init_object(fp->current_object)
+void pgtk__init_object( struct object *o );
+
+void *get_pgdkobject(struct object *from, struct program *type);
+#define get_gdkobject( X, Y ) \
+              (Gdk##Y *)get_pgdkobject( X, pgtk_Gdk##Y##_program )
+
+
+GtkObject *get_pgtkobject(struct object *from, struct program *type);
+#define get_gtkobject( from ) get_pgtkobject( from, pgtk_object_program )
+
+
+void push_gtkobjectclass(void *obj, struct program *def);
+#define push_gtkobject( o ) push_gtkobjectclass(o,pgtk_object_program)
+
+void push_pgdkobject(void *obj, struct program *def);
+#define push_gdkobject( X, Y ) push_pgdkobject( X, pgtk_Gdk##Y##_program )
+
+
+GdkImage *gdkimage_from_pikeimage(struct object *img, int fast, GdkImage *i );
+struct object *pikeimage_from_gdkimage( GdkImage *img );
+
+#define THIS ((struct object_wrapper *)fp->current_storage)
+#define THISO ((struct object_wrapper *)fp->current_storage)->obj
+
+#define GTK_ACCEL_GROUP(X) ((void *)X)
+#define GTK_STYLE(X) ((void *)X)
+
+#define RETURN_THIS()   do{			\
+  pop_n_elems(args);				\
+  ref_push_object( fp->current_object );	\
+} while(0)
+
+struct my_pixel pgtk_pixel_from_xpixel( unsigned int pix, GdkImage *i );
+typedef void *Gdk_Atom;
+GdkAtom get_gdkatom( struct object *o );
+void pgtk_get_mapping_arg( struct mapping *map,
+                           char *name, int type, int madd,
+                           void *dest, long *mask, int len );
+
+void pgtk_index_stack( char *with );
+void pgtk_get_image_module();
+
+
+#if defined(PGTK_DEBUG) && defined(HAVE_GETHRTIME)
+# define TIMER_INIT(X) do { long long cur,last,start; start = gethrtime(); last=start;fprintf(stderr, "%20s ... ",(X))
+# define TIMER_END() cur=gethrtime();fprintf(stderr, "%4.1fms (%4.1fms)\n\n",(cur-last)/1000000.0,(cur-start)/1000000.0);} while(0);
+# define PFTIME(X) cur=gethrtime();fprintf(stderr, "%4.1fms (%4.1fms)\n%20s ... ",(cur-last)/1000000.0,(cur-start)/1000000.0,(X));last=cur;
+# define DEBUG_PF(X) printf X
+#else
+# define TIMER_INIT(X)
+# define PFTIME(X)
+# define TIMER_END()
+# define DEBUG_PF(X) 
+#endif
+
diff --git a/src/post_modules/GTK/source/constants.pre b/src/post_modules/GTK/source/constants.pre
new file mode 100644
index 0000000000000000000000000000000000000000..620c4837c8f3d5b3d320b37a0de0c17f5c0bb59e
--- /dev/null
+++ b/src/post_modules/GTK/source/constants.pre
@@ -0,0 +1,487 @@
+/* -*- c -*- */
+CONSTANT(FALSE);
+CONSTANT(TRUE);
+
+CONSTANT(GTK_CELL_EMPTY);
+CONSTANT(GTK_CELL_TEXT);
+CONSTANT(GTK_CELL_PIXMAP);
+CONSTANT(GTK_CELL_PIXTEXT);
+CONSTANT(GTK_CELL_WIDGET);
+
+CONSTANT(GTK_DIR_TAB_FORWARD);
+CONSTANT(GTK_DIR_TAB_BACKWARD);
+CONSTANT(GTK_DIR_UP);
+CONSTANT(GTK_DIR_DOWN);
+CONSTANT(GTK_DIR_LEFT);
+CONSTANT(GTK_DIR_RIGHT);
+
+CONSTANT(GTK_SHADOW_NONE);
+CONSTANT(GTK_SHADOW_IN);
+CONSTANT(GTK_SHADOW_OUT);
+CONSTANT(GTK_SHADOW_ETCHED_IN);
+CONSTANT(GTK_SHADOW_ETCHED_OUT);
+
+CONSTANT(GTK_ARROW_UP);
+CONSTANT(GTK_ARROW_DOWN);
+CONSTANT(GTK_ARROW_LEFT);
+CONSTANT(GTK_ARROW_RIGHT);
+
+CONSTANT(GTK_PACK_START);
+CONSTANT(GTK_PACK_END);
+
+CONSTANT(GTK_POLICY_ALWAYS);
+CONSTANT(GTK_POLICY_AUTOMATIC);
+CONSTANT(GTK_POLICY_NEVER);
+
+CONSTANT(GTK_UPDATE_CONTINUOUS);
+CONSTANT(GTK_UPDATE_DISCONTINUOUS);
+CONSTANT(GTK_UPDATE_DELAYED);
+
+CONSTANT(GTK_EXPAND);
+CONSTANT(GTK_SHRINK);
+CONSTANT(GTK_FILL);
+
+CONSTANT(GTK_RUN_FIRST);
+CONSTANT(GTK_RUN_LAST);
+CONSTANT(GTK_RUN_BOTH);
+CONSTANT(GTK_RUN_NO_RECURSE);
+
+CONSTANT(GTK_WIN_POS_NONE);
+CONSTANT(GTK_WIN_POS_CENTER);
+CONSTANT(GTK_WIN_POS_MOUSE);
+
+CONSTANT(GTK_DIRECTION_LEFT);
+CONSTANT(GTK_DIRECTION_RIGHT);
+
+CONSTANT(GTK_TOP_BOTTOM);
+CONSTANT(GTK_LEFT_RIGHT);
+
+CONSTANT(GTK_PIXELS);
+CONSTANT(GTK_INCHES);
+CONSTANT(GTK_CENTIMETERS);
+
+CONSTANT(GTK_SCROLL_NONE);
+CONSTANT(GTK_SCROLL_STEP_BACKWARD);
+CONSTANT(GTK_SCROLL_STEP_FORWARD);
+CONSTANT(GTK_SCROLL_PAGE_BACKWARD);
+CONSTANT(GTK_SCROLL_PAGE_FORWARD);
+CONSTANT(GTK_SCROLL_JUMP);
+
+CONSTANT(GTK_TROUGH_NONE);
+CONSTANT(GTK_TROUGH_START);
+CONSTANT(GTK_TROUGH_END);
+CONSTANT(GTK_TROUGH_JUMP);
+
+CONSTANT(GTK_POS_LEFT);
+CONSTANT(GTK_POS_RIGHT);
+CONSTANT(GTK_POS_TOP);
+CONSTANT(GTK_POS_BOTTOM);
+
+CONSTANT(GTK_PREVIEW_COLOR);
+CONSTANT(GTK_PREVIEW_GRAYSCALE);
+
+CONSTANT(GTK_JUSTIFY_LEFT);
+CONSTANT(GTK_JUSTIFY_RIGHT);
+CONSTANT(GTK_JUSTIFY_CENTER);
+CONSTANT(GTK_JUSTIFY_FILL);
+
+CONSTANT(GTK_SELECTION_SINGLE);
+CONSTANT(GTK_SELECTION_BROWSE);
+CONSTANT(GTK_SELECTION_MULTIPLE);
+CONSTANT(GTK_SELECTION_EXTENDED);
+
+CONSTANT(GTK_ORIENTATION_HORIZONTAL);
+CONSTANT(GTK_ORIENTATION_VERTICAL);
+
+CONSTANT(GTK_TOOLBAR_ICONS);
+CONSTANT(GTK_TOOLBAR_TEXT);
+CONSTANT(GTK_TOOLBAR_BOTH);
+
+CONSTANT(GTK_VISIBILITY_NONE);
+CONSTANT(GTK_VISIBILITY_PARTIAL);
+CONSTANT(GTK_VISIBILITY_FULL);
+
+CONSTANT(GTK_BUTTONBOX_DEFAULT_STYLE);
+CONSTANT(GTK_BUTTONBOX_SPREAD);
+CONSTANT(GTK_BUTTONBOX_EDGE);
+CONSTANT(GTK_BUTTONBOX_START);
+CONSTANT(GTK_BUTTONBOX_END);
+
+CONSTANT(GDK_WINDOW_ROOT);
+CONSTANT(GDK_WINDOW_TOPLEVEL);
+CONSTANT(GDK_WINDOW_CHILD);
+CONSTANT(GDK_WINDOW_DIALOG);
+CONSTANT(GDK_WINDOW_TEMP);
+CONSTANT(GDK_WINDOW_PIXMAP);
+CONSTANT(GDK_WINDOW_FOREIGN);
+
+
+CONSTANT(GTK_WINDOW_TOPLEVEL);
+CONSTANT(GTK_WINDOW_DIALOG);
+CONSTANT(GTK_WINDOW_POPUP);
+
+CONSTANT(GTK_STATE_NORMAL);
+CONSTANT(GTK_STATE_ACTIVE);
+CONSTANT(GTK_STATE_PRELIGHT);
+CONSTANT(GTK_STATE_SELECTED);
+CONSTANT(GTK_STATE_INSENSITIVE);
+
+CONSTANT(GTK_CORNER_TOP_LEFT);
+CONSTANT(GTK_CORNER_BOTTOM_LEFT);
+CONSTANT(GTK_CORNER_TOP_RIGHT);
+CONSTANT(GTK_CORNER_BOTTOM_RIGHT);
+
+CONSTANT(GDK_ARROW);
+CONSTANT(GDK_BASED_ARROW_DOWN);
+CONSTANT(GDK_BASED_ARROW_UP);
+CONSTANT(GDK_BOAT);
+CONSTANT(GDK_BOGOSITY);
+CONSTANT(GDK_BOTTOM_LEFT_CORNER);
+CONSTANT(GDK_BOTTOM_RIGHT_CORNER);
+CONSTANT(GDK_BOTTOM_SIDE);
+CONSTANT(GDK_BOTTOM_TEE);
+CONSTANT(GDK_BOX_SPIRAL);
+CONSTANT(GDK_CENTER_PTR);
+CONSTANT(GDK_CIRCLE);
+CONSTANT(GDK_CLOCK);
+CONSTANT(GDK_COFFEE_MUG);
+CONSTANT(GDK_CROSS);
+CONSTANT(GDK_CROSS_REVERSE);
+CONSTANT(GDK_CROSSHAIR);
+CONSTANT(GDK_DIAMOND_CROSS);
+CONSTANT(GDK_DOT);
+CONSTANT(GDK_DOTBOX);
+CONSTANT(GDK_DOUBLE_ARROW);
+CONSTANT(GDK_DRAFT_LARGE);
+CONSTANT(GDK_DRAFT_SMALL);
+CONSTANT(GDK_DRAPED_BOX);
+CONSTANT(GDK_EXCHANGE);
+CONSTANT(GDK_FLEUR);
+CONSTANT(GDK_GOBBLER);
+CONSTANT(GDK_GUMBY);
+CONSTANT(GDK_HAND1);
+CONSTANT(GDK_HAND2);
+CONSTANT(GDK_HEART);
+CONSTANT(GDK_ICON);
+CONSTANT(GDK_IRON_CROSS);
+CONSTANT(GDK_LEFT_PTR);
+CONSTANT(GDK_LEFT_SIDE);
+CONSTANT(GDK_LEFT_TEE);
+CONSTANT(GDK_LEFTBUTTON);
+CONSTANT(GDK_LL_ANGLE);
+CONSTANT(GDK_LR_ANGLE);
+CONSTANT(GDK_MAN);
+CONSTANT(GDK_MIDDLEBUTTON);
+CONSTANT(GDK_MOUSE);
+CONSTANT(GDK_PENCIL);
+CONSTANT(GDK_PIRATE);
+CONSTANT(GDK_PLUS);
+CONSTANT(GDK_QUESTION_ARROW);
+CONSTANT(GDK_RIGHT_PTR);
+CONSTANT(GDK_RIGHT_SIDE);
+CONSTANT(GDK_RIGHT_TEE);
+CONSTANT(GDK_RIGHTBUTTON);
+CONSTANT(GDK_RTL_LOGO);
+CONSTANT(GDK_SAILBOAT);
+CONSTANT(GDK_SB_DOWN_ARROW);
+CONSTANT(GDK_SB_H_DOUBLE_ARROW);
+CONSTANT(GDK_SB_LEFT_ARROW);
+CONSTANT(GDK_SB_RIGHT_ARROW);
+CONSTANT(GDK_SB_UP_ARROW);
+CONSTANT(GDK_SB_V_DOUBLE_ARROW);
+CONSTANT(GDK_SHUTTLE);
+CONSTANT(GDK_SIZING);
+CONSTANT(GDK_SPIDER);
+CONSTANT(GDK_SPRAYCAN);
+CONSTANT(GDK_STAR);
+CONSTANT(GDK_TARGET);
+CONSTANT(GDK_TCROSS);
+CONSTANT(GDK_TOP_LEFT_ARROW);
+CONSTANT(GDK_TOP_LEFT_CORNER);
+CONSTANT(GDK_TOP_RIGHT_CORNER);
+CONSTANT(GDK_TOP_SIDE);
+CONSTANT(GDK_TOP_TEE);
+CONSTANT(GDK_TREK);
+CONSTANT(GDK_UL_ANGLE);
+CONSTANT(GDK_UMBRELLA);
+CONSTANT(GDK_UR_ANGLE);
+CONSTANT(GDK_WATCH);
+CONSTANT(GDK_XTERM);
+
+CONSTANT(GDK_EXTENSION_EVENTS_NONE);
+CONSTANT(GDK_EXTENSION_EVENTS_ALL);
+CONSTANT(GDK_EXTENSION_EVENTS_CURSOR);
+
+CONSTANT(GDK_SELECTION_TYPE_ATOM);
+CONSTANT(GDK_SELECTION_TYPE_BITMAP);
+CONSTANT(GDK_SELECTION_TYPE_COLORMAP);
+CONSTANT(GDK_SELECTION_TYPE_DRAWABLE);
+CONSTANT(GDK_SELECTION_TYPE_INTEGER);
+CONSTANT(GDK_SELECTION_TYPE_PIXMAP);
+CONSTANT(GDK_SELECTION_TYPE_WINDOW);
+CONSTANT(GDK_SELECTION_TYPE_STRING);
+
+CONSTANT(GDK_DECOR_ALL);
+CONSTANT(GDK_DECOR_BORDER);
+CONSTANT(GDK_DECOR_RESIZEH);
+CONSTANT(GDK_DECOR_TITLE);
+CONSTANT(GDK_DECOR_MENU);
+CONSTANT(GDK_DECOR_MINIMIZE);
+CONSTANT(GDK_DECOR_MAXIMIZE);
+
+CONSTANT(GDK_FUNC_ALL);
+CONSTANT(GDK_FUNC_RESIZE);
+CONSTANT(GDK_FUNC_MOVE);
+CONSTANT(GDK_FUNC_MINIMIZE);
+CONSTANT(GDK_FUNC_MAXIMIZE);
+CONSTANT(GDK_FUNC_CLOSE);
+
+CONSTANT(GDK_TARGET_BITMAP);
+CONSTANT(GDK_TARGET_COLORMAP);
+CONSTANT(GDK_TARGET_DRAWABLE);
+CONSTANT(GDK_TARGET_PIXMAP);
+CONSTANT(GDK_TARGET_STRING);
+
+CONSTANT(GDK_SHIFT_MASK);
+CONSTANT(GDK_LOCK_MASK);
+CONSTANT(GDK_CONTROL_MASK);
+CONSTANT(GDK_MOD1_MASK);
+CONSTANT(GDK_MOD2_MASK);
+CONSTANT(GDK_MOD3_MASK);
+CONSTANT(GDK_MOD4_MASK);
+CONSTANT(GDK_MOD5_MASK);
+
+CONSTANT(GTK_TREE_VIEW_LINE);
+CONSTANT(GTK_TREE_VIEW_ITEM);
+
+CONSTANT(GDK_EXPOSURE_MASK);
+CONSTANT(GDK_POINTER_MOTION_MASK);
+CONSTANT(GDK_POINTER_MOTION_HINT_MASK);
+CONSTANT(GDK_BUTTON_MOTION_MASK);
+CONSTANT(GDK_BUTTON1_MOTION_MASK);
+CONSTANT(GDK_BUTTON2_MOTION_MASK);
+CONSTANT(GDK_BUTTON3_MOTION_MASK);
+CONSTANT(GDK_BUTTON1_MASK);
+CONSTANT(GDK_BUTTON2_MASK);
+CONSTANT(GDK_BUTTON3_MASK);
+CONSTANT(GDK_BUTTON_PRESS_MASK);
+CONSTANT(GDK_BUTTON_RELEASE_MASK);
+CONSTANT(GDK_KEY_PRESS_MASK);
+CONSTANT(GDK_KEY_RELEASE_MASK);
+CONSTANT(GDK_ENTER_NOTIFY_MASK);
+CONSTANT(GDK_LEAVE_NOTIFY_MASK);
+CONSTANT(GDK_FOCUS_CHANGE_MASK);
+CONSTANT(GDK_STRUCTURE_MASK);
+CONSTANT(GDK_PROPERTY_CHANGE_MASK);
+CONSTANT(GDK_VISIBILITY_NOTIFY_MASK);
+CONSTANT(GDK_PROXIMITY_IN_MASK);
+CONSTANT(GDK_PROXIMITY_OUT_MASK);
+CONSTANT(GDK_ALL_EVENTS_MASK);
+
+CONSTANT(GDK_PROP_MODE_REPLACE);
+CONSTANT(GDK_PROP_MODE_PREPEND);
+CONSTANT(GDK_PROP_MODE_APPEND);
+
+CONSTANT(GTK_CURVE_TYPE_LINEAR);
+CONSTANT(GTK_CURVE_TYPE_SPLINE);
+CONSTANT(GTK_CURVE_TYPE_FREE);
+
+CONSTANT(GTK_ACCEL_VISIBLE);
+CONSTANT(GTK_ACCEL_SIGNAL_VISIBLE);
+CONSTANT(GTK_ACCEL_LOCKED);
+
+CONSTANT(GTK_RESIZE_PARENT);
+CONSTANT(GTK_RESIZE_QUEUE);
+CONSTANT(GTK_RESIZE_IMMEDIATE);
+
+CONSTANT(GTK_RELIEF_HALF);
+CONSTANT(GTK_RELIEF_NORMAL);
+CONSTANT(GTK_RELIEF_NONE);
+
+
+CONSTANT(GTK_PROGRESS_LEFT_TO_RIGHT);
+CONSTANT(GTK_PROGRESS_RIGHT_TO_LEFT);
+CONSTANT(GTK_PROGRESS_BOTTOM_TO_TOP);
+CONSTANT(GTK_PROGRESS_TOP_TO_BOTTOM);
+
+CONSTANT(GTK_PROGRESS_CONTINUOUS);
+CONSTANT(GTK_PROGRESS_DISCRETE);
+
+CONSTANT(GDK_COPY);
+CONSTANT(GDK_INVERT);
+CONSTANT(GDK_XOR);
+CONSTANT(GDK_CLEAR);
+CONSTANT(GDK_AND);
+CONSTANT(GDK_AND_REVERSE);
+CONSTANT(GDK_AND_INVERT);
+CONSTANT(GDK_NOOP);
+CONSTANT(GDK_OR);
+CONSTANT(GDK_EQUIV);
+CONSTANT(GDK_OR_REVERSE);
+CONSTANT(GDK_COPY_INVERT);
+CONSTANT(GDK_OR_INVERT);
+CONSTANT(GDK_NAND);
+CONSTANT(GDK_SET);
+
+CONSTANT(GDK_SOLID);
+CONSTANT(GDK_TILED);
+CONSTANT(GDK_STIPPLED);
+CONSTANT(GDK_OPAQUE_STIPPLED);
+
+CONSTANT(GDK_EVEN_ODD_RULE);
+CONSTANT(GDK_WINDING_RULE);
+
+CONSTANT(GDK_LINE_SOLID);
+CONSTANT(GDK_LINE_ON_OFF_DASH);
+CONSTANT(GDK_LINE_DOUBLE_DASH);
+
+CONSTANT(GDK_CAP_NOT_LAST);
+CONSTANT(GDK_CAP_BUTT);
+CONSTANT(GDK_CAP_ROUND);
+CONSTANT(GDK_CAP_PROJECTING);
+
+CONSTANT(GDK_JOIN_MITER);
+CONSTANT(GDK_JOIN_ROUND);
+CONSTANT(GDK_JOIN_BEVEL);
+
+CONSTANT(GDK_IM_PREEDIT_AREA);
+CONSTANT(GDK_IM_PREEDIT_CALLBACKS);
+CONSTANT(GDK_IM_PREEDIT_POSITION);
+CONSTANT(GDK_IM_PREEDIT_NOTHING);
+CONSTANT(GDK_IM_PREEDIT_NONE);
+CONSTANT(GDK_IM_PREEDIT_MASK);
+
+CONSTANT(GDK_IM_STATUS_AREA);
+CONSTANT(GDK_IM_STATUS_CALLBACKS);
+CONSTANT(GDK_IM_STATUS_NOTHING);
+CONSTANT(GDK_IM_STATUS_NONE);
+CONSTANT(GDK_IM_STATUS_MASK);
+
+CONSTANT(GDK_OVERLAP_RECTANGLE_IN);
+CONSTANT(GDK_OVERLAP_RECTANGLE_OUT);
+CONSTANT(GDK_OVERLAP_RECTANGLE_PART);
+
+CONSTANT(GDK_ACTION_DEFAULT);
+CONSTANT(GDK_ACTION_COPY);
+CONSTANT(GDK_ACTION_MOVE);
+CONSTANT(GDK_ACTION_LINK);
+CONSTANT(GDK_ACTION_PRIVATE);
+CONSTANT(GDK_ACTION_ASK);
+
+CONSTANT(GTK_DEST_DEFAULT_MOTION);
+CONSTANT(GTK_DEST_DEFAULT_HIGHLIGHT);
+CONSTANT(GTK_DEST_DEFAULT_DROP);
+CONSTANT(GTK_DEST_DEFAULT_ALL);
+
+CONSTANT(GDK_DRAG_PROTO_MOTIF);
+CONSTANT(GDK_DRAG_PROTO_XDND);
+CONSTANT(GDK_DRAG_PROTO_ROOTWIN);
+
+CONSTANT(GTK_FONT_METRIC_PIXELS);
+CONSTANT(GTK_FONT_METRIC_POINTS);
+
+CONSTANT(GTK_FONT_BITMAP);
+CONSTANT(GTK_FONT_SCALABLE);
+CONSTANT(GTK_FONT_SCALABLE_BITMAP);
+CONSTANT(GTK_FONT_ALL);
+
+CONSTANT(GTK_SORT_ASCENDING);
+CONSTANT(GTK_SORT_DESCENDING);
+
+CONSTANT(GTK_TOPLEVEL);
+CONSTANT(GTK_NO_WINDOW);
+CONSTANT(GTK_REALIZED);
+CONSTANT(GTK_MAPPED);
+CONSTANT(GTK_VISIBLE);
+CONSTANT(GTK_SENSITIVE);
+CONSTANT(GTK_PARENT_SENSITIVE);
+CONSTANT(GTK_CAN_FOCUS);
+CONSTANT(GTK_HAS_FOCUS);
+CONSTANT(GTK_CAN_DEFAULT);
+CONSTANT(GTK_HAS_DEFAULT);
+CONSTANT(GTK_HAS_GRAB);
+CONSTANT(GTK_RC_STYLE);
+CONSTANT(GTK_COMPOSITE_CHILD);
+CONSTANT(GTK_NO_REPARENT);
+CONSTANT(GTK_APP_PAINTABLE);
+
+CONSTANT(GTK_SPIN_STEP_FORWARD);
+CONSTANT(GTK_SPIN_STEP_BACKWARD);
+CONSTANT(GTK_SPIN_PAGE_FORWARD);
+CONSTANT(GTK_SPIN_PAGE_BACKWARD);
+CONSTANT(GTK_SPIN_HOME);
+CONSTANT(GTK_SPIN_END);
+CONSTANT(GTK_SPIN_USER_DEFINED);  
+CONSTANT(GTK_UPDATE_ALWAYS);
+CONSTANT(GTK_UPDATE_IF_VALID);
+
+CONSTANT(GTK_CLIST_IN_DRAG);
+CONSTANT(GTK_CLIST_ROW_HEIGHT_SET);
+CONSTANT(GTK_CLIST_SHOW_TITLES);
+CONSTANT(GTK_CLIST_CHILD_HAS_FOCUS);
+CONSTANT(GTK_CLIST_ADD_MODE);
+CONSTANT(GTK_CLIST_AUTO_SORT);
+CONSTANT(GTK_CLIST_AUTO_RESIZE_BLOCKED);
+CONSTANT(GTK_CLIST_REORDERABLE);
+CONSTANT(GTK_CLIST_USE_DRAG_ICONS);
+CONSTANT(GTK_CLIST_DRAW_DRAG_LINE);
+CONSTANT(GTK_CLIST_DRAW_DRAG_RECT);
+
+CONSTANT(GTK_BUTTON_IGNORED);
+CONSTANT(GTK_BUTTON_SELECTS);
+CONSTANT(GTK_BUTTON_DRAGS);
+CONSTANT(GTK_BUTTON_EXPANDS);
+
+CONSTANT(GTK_PACK_EXPAND);
+CONSTANT(GTK_FILL_X);
+CONSTANT(GTK_FILL_Y);
+
+CONSTANT(GTK_SIDE_TOP);
+CONSTANT(GTK_SIDE_BOTTOM);
+CONSTANT(GTK_SIDE_LEFT);
+CONSTANT(GTK_SIDE_RIGHT);
+
+CONSTANT(GTK_ANCHOR_CENTER);
+CONSTANT(GTK_ANCHOR_NORTH);
+CONSTANT(GTK_ANCHOR_NORTH_WEST);
+CONSTANT(GTK_ANCHOR_NORTH_EAST);
+CONSTANT(GTK_ANCHOR_SOUTH);
+CONSTANT(GTK_ANCHOR_SOUTH_WEST);
+CONSTANT(GTK_ANCHOR_SOUTH_EAST);
+CONSTANT(GTK_ANCHOR_WEST);
+CONSTANT(GTK_ANCHOR_EAST);
+CONSTANT(GTK_ANCHOR_N);
+CONSTANT(GTK_ANCHOR_NW);
+CONSTANT(GTK_ANCHOR_NE);
+CONSTANT(GTK_ANCHOR_S);
+CONSTANT(GTK_ANCHOR_SW);
+CONSTANT(GTK_ANCHOR_SE);
+CONSTANT(GTK_ANCHOR_W);
+CONSTANT(GTK_ANCHOR_E);
+
+CONSTANT(GTK_CTREE_POS_BEFORE);
+CONSTANT(GTK_CTREE_POS_AS_CHILD);
+CONSTANT(GTK_CTREE_POS_AFTER);
+
+CONSTANT(GTK_CTREE_LINES_NONE);
+CONSTANT(GTK_CTREE_LINES_SOLID);
+CONSTANT(GTK_CTREE_LINES_DOTTED);
+CONSTANT(GTK_CTREE_LINES_TABBED);
+
+CONSTANT(GTK_CTREE_EXPANDER_NONE);
+CONSTANT(GTK_CTREE_EXPANDER_SQUARE);
+CONSTANT(GTK_CTREE_EXPANDER_TRIANGLE);
+CONSTANT(GTK_CTREE_EXPANDER_CIRCULAR);
+
+CONSTANT(GTK_CTREE_EXPANSION_EXPAND);
+CONSTANT(GTK_CTREE_EXPANSION_EXPAND_RECURSIVE);
+CONSTANT(GTK_CTREE_EXPANSION_COLLAPSE);
+CONSTANT(GTK_CTREE_EXPANSION_COLLAPSE_RECURSIVE);
+CONSTANT(GTK_CTREE_EXPANSION_TOGGLE);
+CONSTANT(GTK_CTREE_EXPANSION_TOGGLE_RECURSIVE);
+
+CONSTANT(GTK_CALENDAR_SHOW_HEADING);
+CONSTANT(GTK_CALENDAR_SHOW_DAY_NAMES);
+CONSTANT(GTK_CALENDAR_NO_MONTH_CHANGE);
+CONSTANT(GTK_CALENDAR_SHOW_WEEK_NUMBERS);
+CONSTANT(GTK_CALENDAR_WEEK_START_MONDAY);
diff --git a/src/post_modules/GTK/source/encode_truecolor.c b/src/post_modules/GTK/source/encode_truecolor.c
new file mode 100644
index 0000000000000000000000000000000000000000..98d50ff44c9418ead09d1339e6a3ba8c061f4689
--- /dev/null
+++ b/src/post_modules/GTK/source/encode_truecolor.c
@@ -0,0 +1,419 @@
+#define COLORTYPE unsigned char
+
+typedef struct { unsigned char r,g,b; } rgb_group;
+
+struct image
+{
+   rgb_group *img;
+   int xsize,ysize;
+};
+
+static unsigned char swap_bits[256] = 
+{ 0,128,64,192,32,160,96,224,16,144,80,208,48,176,112,
+  240,8,136,72,200,40,168,104,232,24,152,88,216,56,184,
+  120,248,4,132,68,196,36,164,100,228,20,148,84,212,52,
+  180,116,244,12,140,76,204,44,172,108,236,28,156,92,220,
+  60,188,124,252,2,130,66,194,34,162,98,226,18,146,82,
+  210,50,178,114,242,10,138,74,202,42,170,106,234,26,154,
+  90,218,58,186,122,250,6,134,70,198,38,166,102,230,22,
+  150,86,214,54,182,118,246,14,142,78,206,46,174,110,238,
+  30,158,94,222,62,190,126,254,1,129,65,193,33,161,97,
+  225,17,145,81,209,49,177,113,241,9,137,73,201,41,169,
+  105,233,25,153,89,217,57,185,121,249,5,133,69,197,37,
+  165,101,229,21,149,85,213,53,181,117,245,13,141,77,205,
+  45,173,109,237,29,157,93,221,61,189,125,253,3,131,67,
+  195,35,163,99,227,19,147,83,211,51,179,115,243,11,139,
+  75,203,43,171,107,235,27,155,91,219,59,187,123,251,7,
+  135,71,199,39,167,103,231,23,151,87,215,55,183,119,247,
+  15,143,79,207,47,175,111,239,31,159,95,223,63,191,127,255};
+
+
+
+static void encode_truecolor_24_rgb_swapped( rgb_group *s,
+                                             unsigned char *d,
+                                             int q, int w )
+{
+  while(q--)
+  {
+    *(d++) = s->b;
+    *(d++) = s->g;
+    *(d++) = (s++)->r;
+  }
+}
+
+static void encode_truecolor_24_rgb( rgb_group *s,
+                                     unsigned char *d,
+                                     int q, int w )
+{
+  MEMCPY(d,(unsigned char *)s,q);
+}
+
+static void encode_truecolor_24_rgb_al32_swapped( rgb_group *s,
+                                                  unsigned char *d,
+                                                  int q, int w )
+{
+  int l;
+  while(q)
+  {
+    l=w;
+    while(l--)
+    {
+      *(d++) = s->b;
+      *(d++) = s->g;
+      *(d++) = (s++)->r;
+      q--;
+    }
+    d += (w*3)&3;
+  }
+}
+
+static void encode_truecolor_24_rgb_al32( rgb_group *s,
+                                          unsigned char *d,
+                                          int q, int w )
+{
+  int l;
+  while(q)
+  {
+    for(l=0; l<(q/w)/3; l++)
+    {
+      MEMCPY(d,(unsigned char *)s,w*3);
+      d += (w*3)&3;
+    }
+  }
+}
+
+
+#define encode_truecolor_24_bgr encode_truecolor_24_rgb_swapped
+#define encode_truecolor_24_bgr_swapped encode_truecolor_24_rgb
+#define encode_truecolor_24_bgr_al32 encode_truecolor_24_rgb_al32_swapped
+#define encode_truecolor_24_bgr_al32_swapped encode_truecolor_24_rgb_al32
+
+#include <machine.h>
+#ifdef TRY_USE_MMX
+#include <mmx.h>
+extern int try_use_mmx;
+#endif
+static void encode_truecolor_32_argb_swapped( rgb_group *s,
+                                              unsigned char *d,
+                                              int q,int w )
+{
+  int *dp = (int *)d;
+#if PIKE_BYTEORDER==1234
+  while(q--) *(dp++) = (s->r<<16) | (s->g<<8) | (s++)->b;
+#else
+  while(q--) *(dp++) = ((s->r) | (s->g<<8) | (s++)->b<<16)<<8;
+#endif
+}
+
+static void encode_truecolor_32_argb( rgb_group *s,
+                                      unsigned char *d,
+                                      int q,int w )
+{
+  int *dp = (int *)d;
+#if PIKE_BYTEORDER==4321
+  while(q--) *(dp++) = (s->r<<16) | (s->g<<8) | (s++)->b;
+#else
+  while(q--) *(dp++) = ((s->r) | (s->g<<8) | (s++)->b<<16)<<8;
+#endif
+}
+
+static void encode_truecolor_32_abgr( rgb_group *s,
+                                      unsigned char *d,
+                                      int q,int w )
+{
+  while(q--)
+  {
+    *(d++) = 0;
+    *(d++) = s->b;
+    *(d++) = s->g;
+    *(d++) = (s++)->r;
+  }
+}
+
+
+static void encode_truecolor_32_abgr_swapped( rgb_group *s,
+                                              unsigned char *d,
+                                              int q,int w )
+{
+  while(q--)
+  {
+    *(d++) = s->r;
+    *(d++) = s->g;
+    *(d++) = (s++)->b;
+    *(d++) = 0;
+  }
+}
+
+#define ENCODE_8(X,Y,Z)                                                              \
+static void encode_truecolor_##X##_##Y( rgb_group *s, unsigned char *d, int q,int w )           \
+{                                                                       \
+  while(q--)                                                            \
+    *(d++)=(Z);                                                         \
+}                                                                       \
+                                                                        \
+static void encode_truecolor_##X##_##Y##_swapped( rgb_group *s, unsigned char *d, int q ,int w) \
+{                                                                       \
+  while(q--)                                                            \
+    *(d++)=(Z);                                                         \
+}
+
+
+#if PIKE_BYTEORDER == 1234
+#define ENCODE_16(X,Y,Z)                                                              \
+static void encode_truecolor_##X##_##Y( rgb_group *s, unsigned char *d, int q,int w )           \
+{                                                                       \
+  unsigned short *dp = (unsigned short *)d;                             \
+  while(q--)                                                            \
+    *(dp++) = (Z);                                                      \
+}                                                                       \
+                                                                        \
+static void encode_truecolor_##X##_##Y##_swapped( rgb_group *s, unsigned char *d, int q ,int w) \
+{                                                                       \
+  while(q--)                                                            \
+  {                                                                     \
+    unsigned short v = (Z);                                             \
+    *(d++)=v&255;                                                       \
+    *(d++)=v>>8;                                                        \
+  }                                                                     \
+}
+#else
+#define ENCODE_16(X,Y,Z)                                                              \
+static void encode_truecolor_##X##_##Y( rgb_group *s, unsigned char *d, int q,int w )           \
+{                                                                       \
+  while(q--)                                                            \
+  {                                                                     \
+    unsigned short v = (Z);                                             \
+    *(d++)=v>>8;                                                        \
+    *(d++)=v&255;                                                       \
+  }                                                                     \
+}                                                                       \
+                                                                        \
+static void encode_truecolor_##X##_##Y##_swapped( rgb_group *s, unsigned char *d, int q ,int w) \
+{                                                                       \
+  unsigned short *dp = (unsigned short *)d;                             \
+  while(q--)                                                            \
+    *(dp++) = (Z);                                                      \
+}
+#endif
+
+ENCODE_16(565,rgb,((s->r>>3)<<11) | (s->g>>2)<<5 | ((s++)->b>>3));
+ENCODE_16(565,bgr,((s->b>>3)<<11) | (s->g>>2)<<5 | ((s++)->r>>3));
+ENCODE_16(555,rgb,((s->r>>3)<<10) | (s->g>>3)<<5 | ((s++)->b>>3));
+ENCODE_16(555,bgr,((s->b>>3)<<10) | (s->g>>3)<<5 | ((s++)->r>>3));
+
+ENCODE_8(232,rgb,((s->r>>6)<<5) | (s->g>>5)<<2 | ((s++)->b>>6));
+ENCODE_8(332,rgb,((s->r>>5)<<5) | (s->g>>5)<<2 | ((s++)->b>>6));
+ENCODE_8(242,rgb,((s->r>>5)<<6) | (s->g>>4)<<2 | ((s++)->b>>6));
+ENCODE_8(233,rgb,((s->r>>5)<<6) | (s->g>>4)<<3 | ((s++)->b>>5));
+ENCODE_8(232,bgr,((s->b>>6)<<5) | (s->g>>5)<<2 | ((s++)->r>>6));
+ENCODE_8(332,bgr,((s->b>>5)<<5) | (s->g>>5)<<2 | ((s++)->r>>6));
+ENCODE_8(242,bgr,((s->b>>5)<<6) | (s->g>>4)<<2 | ((s++)->r>>6));
+ENCODE_8(233,bgr,((s->b>>5)<<6) | (s->g>>4)<<3 | ((s++)->r>>5));
+
+
+static void encode_truecolor_generic(int rbits, int rshift, int gbits, 
+                                     int gshift, int bbits, int bshift, 
+                                     int bpp, int alignbits,int swap_bytes, 
+                                     struct image *img, unsigned char *dest,
+                                     int len)
+{
+   unsigned char *d = dest;
+   int x,y;
+   rgb_group *s;
+   s=img->img;
+
+   if(!alignbits) alignbits=1;
+
+#define OPTIMIZE(rb,rs,gb,gs,bb,bs,al,fun) if(rbits==rb&&rshift==rs&&gbits==gb&&gshift==gs&&bbits==bb&&bshift==bs&&alignbits==al) {DEBUG_PF(("Optimized case %s%s\n",#fun,swap_bytes?"_swapped":"")); return (swap_bytes?fun##_swapped(s,(void *)dest,img->xsize*img->ysize,img->xsize):fun(s,(void *)dest,img->xsize*img->ysize,img->xsize));}
+
+   switch(bpp)
+   {
+    case 32: /* 4 alternatives */
+      OPTIMIZE(8,16,8,8,8,0,1,encode_truecolor_32_argb);
+      OPTIMIZE(8,0,8,8,8,16,1,encode_truecolor_32_abgr);
+      break;
+    case 24: /* 8 alternatives */
+      OPTIMIZE(8,16,8,8,8,0,32,encode_truecolor_24_rgb_al32);
+      OPTIMIZE(8,0,8,8,8,16,32,encode_truecolor_24_bgr_al32);
+      OPTIMIZE(8,16,8,8,8,0,1,encode_truecolor_24_rgb);
+      OPTIMIZE(8,0,8,8,8,16,1,encode_truecolor_24_bgr);
+      break;
+    case 16: /* 8 alternatives */
+      OPTIMIZE(5,11,6,5,5,0,1,encode_truecolor_565_rgb);
+      OPTIMIZE(5,10,5,5,5,0,1,encode_truecolor_555_rgb);
+      OPTIMIZE(5,0,6,5,5,11,1,encode_truecolor_565_bgr);
+      OPTIMIZE(5,0,5,5,5,10,1,encode_truecolor_555_bgr);
+      break;
+    case 8: /* 16 alternatives */
+      OPTIMIZE(2,5,3,2,2,0,1,encode_truecolor_232_rgb);
+      OPTIMIZE(3,5,3,2,2,0,1,encode_truecolor_332_rgb);
+      OPTIMIZE(2,6,4,2,2,0,1,encode_truecolor_242_rgb);
+      OPTIMIZE(2,6,3,3,3,0,1,encode_truecolor_233_rgb);
+      OPTIMIZE(2,0,3,2,2,5,1,encode_truecolor_232_bgr);
+      OPTIMIZE(3,0,3,2,2,5,1,encode_truecolor_332_bgr);
+      OPTIMIZE(2,0,4,2,2,6,1,encode_truecolor_242_bgr);
+      OPTIMIZE(2,0,3,3,3,6,1,encode_truecolor_233_bgr);
+      break;
+   }
+#undef OPTIMIZE
+
+   DEBUG_PF(("Generic encode_truecolor for r%dxg%dxb%d (%d bpp, shift=r%d,g%d,b%d)\n",
+             rbits,gbits,bbits,bpp,rshift,gshift,bshift));
+   {
+     int rfmask,gfmask,bfmask;
+     int rfshift,gfshift,bfshift,rzshift,gzshift,bzshift;
+     int bpshift,blinemod,bit;
+
+     *d=0;
+
+     rfshift=rshift-(sizeof(COLORTYPE)*8-rbits);
+     gfshift=gshift-(sizeof(COLORTYPE)*8-gbits);
+     bfshift=bshift-(sizeof(COLORTYPE)*8-bbits);
+     if (rfshift<0) rzshift=-rfshift,rfshift=0; else rzshift=0;
+     if (gfshift<0) gzshift=-gfshift,gfshift=0; else gzshift=0;
+     if (bfshift<0) bzshift=-bfshift,bfshift=0; else bzshift=0;
+
+     rfmask=(((1<<rbits)-1)<<(sizeof(COLORTYPE)*8-rbits));
+     gfmask=(((1<<gbits)-1)<<(sizeof(COLORTYPE)*8-gbits));
+     bfmask=(((1<<bbits)-1)<<(sizeof(COLORTYPE)*8-bbits));
+     bpshift=sizeof(unsigned long)*8-bpp;
+     blinemod=alignbits-(((img->xsize*bpp+7)&~7)%alignbits);
+     if(blinemod==alignbits)
+       blinemod=0;
+     else
+       blinemod>>=3;
+
+     bit=0;
+     y = img->ysize;
+     while (y--)
+     {
+       int bp;
+       x=img->xsize;
+       while (x--)
+       {
+         register unsigned long b =
+           ((((s->r&rfmask)>>rzshift)<<rfshift)|
+            (((s->g&gfmask)>>gzshift)<<gfshift)|
+            (((s->b&bfmask)>>bzshift)<<bfshift))<<bpshift;
+         bp = bpp;
+         while (bp>8-bit)
+         {
+	   if(bit)
+	     *d|=(unsigned char)(b>>(24+bit));
+	   else
+	     *d=(unsigned char)(b>>24);
+           b<<=8-bit;
+           bp-=8-bit;
+           bit=0;
+	   d++;
+         }
+	 if(bit)
+	   *d|=b>>(24+bit); 
+	 else
+	   *d=b>>24;
+         bit+=bp;
+         if (bit==8) ++d,bit=0;
+         s++;
+       }
+       if(!y)
+	 break;
+       if(bit) ++d,bit=0;
+       bp=blinemod;
+       while (bp--) *(++d)=0;
+     }
+   }
+
+   if (swap_bytes)
+   {
+     d=dest;
+     x=len;
+
+     switch (bpp)
+     {
+      case 32:
+        while (x>=4)
+        {
+          d[0]^=d[3],d[3]^=d[0],d[0]^=d[3];
+          d[1]^=d[2],d[2]^=d[1],d[1]^=d[2];
+          d+=4;
+          x-=4;
+        }
+        break;
+      case 24:
+        while (x>=3)
+        {
+          d[0]^=d[2],d[2]^=d[0],d[0]^=d[2];
+          d+=3;
+          x-=3;
+        }
+        break;
+      case 16:
+        while (x>=2)
+        {
+          d[0]^=d[1],d[1]^=d[0],d[0]^=d[1];
+          d+=2;
+          x-=2;
+        }
+        break;
+      case 1: 
+        while (x--) *(d++)=swap_bits[*d];      
+        break;
+     }
+   }
+}
+
+static INLINE void examine_mask(unsigned int x, int *bits,int *shift)
+{
+   *bits=0; 
+   *shift=0; 
+   if (!x) return;
+   while (!(x&1)) x>>=1,(*shift)++;
+   while (x&1) x>>=1,(*bits)++;
+}
+
+void pgtk_encode_grey(struct image *i, unsigned char *dest, int bpp, int bpl )
+{
+  int x, y;
+  rgb_group *s = i->img;
+  switch(bpp)
+  {
+   case 1:
+     for(y=0; y<i->ysize; y++)
+     {
+       unsigned char *d = dest+y*bpl;
+       for(x=0; x<i->xsize; x++)
+         *d = (s->r + s->g*2 + (s++)->b)>>2;
+     }
+     return;
+   case 2:
+     for(y=0; y<i->ysize; y++)
+     {
+       unsigned short *d = (unsigned short *)(dest+y*bpl);
+       for(x=0; x<i->xsize; x++)
+         *d = (s->r + s->g*2 + (s++)->b)<<6;
+     }
+     return;
+   default:
+     error("This greyscale is to wide for me!\n");
+  }
+}
+
+void pgtk_encode_truecolor_masks(struct image *i,
+                                 int bitspp,
+                                 int pad,
+                                 int byteorder,
+                                 unsigned int red_mask,
+                                 unsigned int green_mask,
+                                 unsigned int blue_mask,
+                                 unsigned char *buffer, 
+                                 int debug_len)
+{
+   int rbits,rshift,gbits,gshift,bbits,bshift;
+
+  examine_mask(red_mask,&rbits,&rshift);
+  examine_mask(green_mask,&gbits,&gshift);
+  examine_mask(blue_mask,&bbits,&bshift);
+  encode_truecolor_generic( rbits, rshift, gbits, gshift, bbits, bshift,
+                            bitspp, pad, byteorder, i, buffer, debug_len );
+
+}
diff --git a/src/post_modules/GTK/source/gdkatom.pre b/src/post_modules/GTK/source/gdkatom.pre
new file mode 100644
index 0000000000000000000000000000000000000000..8b5fbc4c54ee35cf8a4a36ff5ffae5e2d4f3554c
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkatom.pre
@@ -0,0 +1,22 @@
+PROGRAM(Gdk_Atom);
+// An X-atom. You most likely want to use GDK.Atom.atom_name 
+// instead of Gdk_Atom(name).
+FUNCTION(create, "function(string,int|void:void)");
+NAME_ARGS(atom_name, only_if_exists);
+// Create a new low-level atom. You should normally not call this
+// function directly. Use GDK.Atom[name] instead of GDK._Atom(name,0).
+{
+  char *atom_name;
+  int only_if_exists;
+  get_all_args("GDK.Atom( string, int )",args,"%s%d",&atom_name,&only_if_exists);
+  THIS->obj = (void *)gdk_atom_intern( atom_name, only_if_exists );
+  pop_n_elems(args);
+  push_int(0);
+}
+
+FUNCTION(get_name, "function(void:string)");
+// Returns the name of the atom.
+{
+  pop_n_elems(args);
+  push_text( gdk_atom_name( (GdkAtom)THIS->obj ) );
+}
diff --git a/src/post_modules/GTK/source/gdkbitmap.pre b/src/post_modules/GTK/source/gdkbitmap.pre
new file mode 100644
index 0000000000000000000000000000000000000000..1622d82b32c6aa2f13782d9319781f658ffeaeef
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkbitmap.pre
@@ -0,0 +1,45 @@
+PROGRAM(GdkBitmap);
+INHERIT(GdkDrawable);
+// A bitmap is a black and white pixmap. Most commonly used as masks
+// for images, widgets and pixmaps.
+//
+// NOIMG
+FUNCTION(create, "function(int|object,int|void,string|void:void)")
+ARGS(object(Image.image)|int,void|int,void|string);
+NAME_ARGS(image|xsize, void|ysize, void|xbitmapdata);
+// Create a new gdkBitmap object. 
+// Argument is either an Image.image object, or {xsisze,ysize,xbitmapdata}.
+{
+  int x, y;
+  char *d;
+  if(args == 3)
+  {
+    get_all_args("create", args, "%d%d%s", &x, &y, &d );
+  } else if(args==1) {
+    struct object *o;
+    get_all_args("create", args, "%o", &o );
+    apply(o, "xsize", 0);  get_all_args("internal", 1, "%d", &x ); pop_stack();
+    apply(o, "ysize", 0);  get_all_args("internal", 1, "%d", &y ); pop_stack();
+
+    /* Now we have the image size.. Lets create the bitmap... */
+    apply(o, "tobitmap", 0);
+    get_all_args( "internal", 1, "%s", &d );
+    args=2; /* evil me.. */
+  } else {
+    error("Wrong number of arguments to GDK.Bitmap()\n");
+  }
+
+  THIS->obj = (void *)gdk_bitmap_create_from_data(0, d, x, y);
+  if(!THIS->obj)
+    error("Failed to create bitmap\n");
+  pop_n_elems(args);
+}
+
+FUNCTION(destroy, "function(void:void)");
+// Destructor. Destroys the bitmap. This will free the bitmap on the X-server.
+{
+  if(THIS->obj)
+    gdk_bitmap_unref( (void *)THIS->obj );
+  THIS->obj = 0;
+}
+
diff --git a/src/post_modules/GTK/source/gdkcolor.pre b/src/post_modules/GTK/source/gdkcolor.pre
new file mode 100644
index 0000000000000000000000000000000000000000..3f755134359fe521f146857e0cbf7b99cbab319f
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkcolor.pre
@@ -0,0 +1,103 @@
+PROGRAM(GdkColor);
+// The GDK.Color object is used to represent a color.
+// When you call GDK.Color(r,g,b) the color will be allocated 
+// from the X-server. The constructor can return an  exception if there are
+// no more colors to allocate.
+// NOIMG
+FUNCTION(create, "function(object|int,int|void,int|void:void)")
+NAME_ARGS(r|color,g,b);
+// r g and b are in the range 0 to 255, inclusive.
+// If color is specified, it should be an Image.Color object, and the
+// only argument.
+{
+  int r,g,b;
+  GdkColormap *col = gdk_colormap_get_system();
+  GdkColor *c;
+  if( args == 1)
+  {
+    struct object *o;
+    get_all_args("GdkColor", args, "%o", &o);
+    if( !get_color_from_pikecolor( o, &r, &g, &b ) )
+      error("Bad argument 1 to GDK.Color(). Exptected color object\n");
+  }
+  else
+  {
+    get_all_args("GdkColor", args, "%d%d%d", &r, &g, &b);
+    r*=257;
+    g*=257;
+    b*=257;
+  }
+    
+  c = malloc(sizeof(GdkColor));
+  THIS->obj = (void *)c;
+  c->red   = r;
+  c->green = g;
+  c->blue  = b;
+  c->pixel = 0;
+  if(!gdk_color_alloc( col, c ))
+  {
+    free(c);
+    THIS->obj = 0;
+    error("Failed to allocate color.\n");
+  }
+}
+
+FUNCTION(rgb, "function(void:array(int))")
+// Returns the red green and blue color components as an array.
+{
+  push_int(((GdkColor *)THIS->obj)->red/257);
+  push_int(((GdkColor *)THIS->obj)->green/257);
+  push_int(((GdkColor *)THIS->obj)->blue/257);
+  f_aggregate(3);
+}
+
+FUNCTION(red, "function(void:int)")
+// Returns the red color component.
+{
+  push_int(((GdkColor *)THIS->obj)->red/257);
+}
+
+FUNCTION(green, "function(void:int)")
+// Returns the green color component.
+{
+  push_int(((GdkColor *)THIS->obj)->green/257);
+}
+
+FUNCTION(blue, "function(void:int)")
+// Returns the blue color component.
+{
+  push_int(((GdkColor *)THIS->obj)->blue/257);
+}
+
+FUNCTION(pixel, "function(void:int)")
+// Returns the pixel value of the color. See <a href=GdkImage.html#set_pixel>GDK.Image->set_pixel</a>.
+{
+  push_int(((GdkColor *)THIS->obj)->pixel);
+}
+
+FUNCTION(image_color_object, "function(void:object)");
+// Return a Image.Color.Color instance.<br>
+// This gives better precision than the rgb function.
+{
+  unsigned char colorname[4+4+4+2]; 
+  sprintf( colorname, "#%04x%04x%04x", 
+           ((GdkColor *)THIS->obj)->red,
+           ((GdkColor *)THIS->obj)->green,
+           ((GdkColor *)THIS->obj)->blue );
+
+  pop_n_elems(args);
+  pgtk_get_image_module();
+  pgtk_index_stack( "Color" );
+  pgtk_index_stack(colorname);
+}
+
+FUNCTION(destroy, "function(void:void)")
+// Destroys the color object. Please note that this function does
+// _not_ free the color from the X-colormap right now.
+{
+  if(THIS->obj)
+  {
+    free(THIS->obj);
+    THIS->obj = 0;
+  }
+}
diff --git a/src/post_modules/GTK/source/gdkdragcontext.pre b/src/post_modules/GTK/source/gdkdragcontext.pre
new file mode 100644
index 0000000000000000000000000000000000000000..212943a3104fec14e456d4767185c24f99f209b8
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkdragcontext.pre
@@ -0,0 +1,135 @@
+PROGRAM(GdkDragContext);
+// The drag context contains all information about the drag'n'drop
+// connected to the signal.
+// <p>
+// NOIMG
+#define GTK_GDKDRAGCONTEXT(X) ((GdkDragContext *)X)
+
+FUNCTION(get_source_widget, "function(void:object)");
+// Return the drag source widget.
+RETURNS(GTK.Widget);
+{
+  pop_n_elems(args);
+  push_gtkobjectclass(gtk_drag_get_source_widget(((GdkDragContext *)THIS->obj)),
+                      pgtk_widget_program);
+}
+
+FUNCTION(drag_finish, "function(int,int,int:object)");
+RETURNS(GDK.DragContext);
+NAME_ARGS(success,del,time);
+// If success is true, the drag succeded.
+// If del is true, the source should be deleted.
+// time is the current time. 
+{
+  int a, b, t;
+  get_all_args("drag_finish", args, "%d%d%d", &a, &b, &t );
+  gtk_drag_finish(((GdkDragContext *)THIS->obj), a, b, t);
+  RETURN_THIS();
+}
+
+FUNCTION(drag_status, "function(int,int|void:object)");
+RETURNS(GDK.DragContext);
+NAME_ARGS( action );
+{
+  time_t curtime = time(0);
+  gdk_drag_status( ((GdkDragContext *)THIS->obj), 
+                   (args?sp[-1].u.integer:
+                    ((GdkDragContext *)THIS->obj)->suggested_action),
+                   curtime);
+  RETURN_THIS();
+}
+
+FUNCTION(drag_drop, "function(int:object)");
+NAME_ARGS(time);
+{
+  int t;
+  get_all_args( "drop", args, "%d", &t );
+  gdk_drag_drop( ((GdkDragContext *)THIS->obj), t);
+  RETURN_THIS();
+}
+
+
+FUNCTION(drag_abort, "function(int:object)");
+NAME_ARGS(time);
+// Abort the drag
+{
+  int t;
+  get_all_args( "abort", args, "%d", &t );
+  gdk_drag_abort( ((GdkDragContext *)THIS->obj), t);
+  RETURN_THIS();
+}
+
+FUNCTION(drop_reply, "function(int,int:object)");
+NAME_ARGS(ok,time);
+{
+  int t, o;
+  get_all_args( "reply", args, "%d%d", &o, &t );
+  gdk_drop_reply( ((GdkDragContext *)THIS->obj), o, t);
+  RETURN_THIS();
+}
+
+
+
+FUNCTION(drag_set_icon_widget, "function(object,int,int,int:object)");
+NAME_ARGS(widget,hot_x,hot_y);
+ARGS(GTK.Widget,int,int);
+// Set the drag widget. This is a widget that will be shown, and then
+// dragged around by the user during this drag.
+{
+  struct object *_o;
+  int x, y;
+  get_all_args( "drag_set_icon_window", args, "%o%d%d", 
+                &_o, &x, &y);
+  gtk_drag_set_icon_widget( ((GdkDragContext *)THIS->obj),
+                            GTK_WIDGET(get_pgtkobject( _o, pgtk_widget_program )),
+                            x,y );
+  RETURN_THIS();
+}
+
+FUNCTION(drag_set_icon_default, "function(void:object)");
+// Use the default drag icon associated with the source widget.
+{
+  gtk_drag_set_icon_default( ((GdkDragContext *)THIS->obj) );
+  RETURN_THIS();
+}
+
+FUNCTION(drag_set_icon_pixmap, "function(object,object|void,int,int:object)");
+RETURNS(GTK.Widget);
+ARGS(GTK.Pixmap,GTK.Bitmap,int,int);
+NAME_ARGS(image,mask,hot_x,hot_y);
+// Set the drag pixmap, and optionally mask.<br>
+// The hot_x and hot_y coordinates will be the location of the mouse pointer, 
+// relative to the upper left corner of the pixmap.
+{
+  struct object *p=NULL, *m=NULL;
+  int x, y;
+  if(args != 4)
+    error("Too few arguments to drag_set_icon_pixmap\n");
+  if(sp[-args].type == T_OBJECT)
+    p = sp[-args].u.object;
+  if(sp[-args+1].type == T_OBJECT)
+    m = sp[-args+1].u.object;
+  x  = sp[-args+2].u.integer;
+  y  = sp[-args+3].u.integer;
+
+  gtk_drag_set_icon_pixmap( ((GdkDragContext *)THIS->obj),
+                            gdk_colormap_get_system(),
+                            get_gdkobject( p, Pixmap ),
+                            get_gdkobject( m, Bitmap ),
+                             x,y);
+  RETURN_THIS();
+}
+
+
+CLASSMEMBER(suggested_action, int);
+// One of CONST(GDK_ACTION);
+CLASSMEMBER(actions, int);
+// A bitwise or of one or more of CONST(GDK_ACTION);
+CLASSMEMBER(action, int);
+// One of CONST(GDK_ACTION);
+CLASSMEMBER(start_time, int);
+// The start time of this drag, as a unix time_t (seconds since 0:00 1/1 1970)
+CLASSMEMBER(protocol, int);
+// One of CONST(GDK_DRAG_PROTO)
+CLASSMEMBER(is_source, int);
+// Is this application the source?
diff --git a/src/post_modules/GTK/source/gdkdrawable.pre b/src/post_modules/GTK/source/gdkdrawable.pre
new file mode 100644
index 0000000000000000000000000000000000000000..97ed8255801f07a5f4b9b219b6156c2f7d51310a
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkdrawable.pre
@@ -0,0 +1,236 @@
+PROGRAM(GdkDrawable);
+// The GDK.Bitmap, GDK.Window and GDK.Pixmap classes are all GDK drawables.
+// <br>
+// This means that you can use the same set of functions to draw in them.<br>
+// <p>
+// Pixmaps are offscreen drawables. They can be drawn upon with the
+// standard drawing primitives, then copied to another drawable (such
+// as a GDK.Window) with window->draw_pixmap(), set as the background
+// for a window or widget, or otherwise used to show graphics (in a
+// W(Pixmap), as an example). The depth of a pixmap is the number of
+// bits per pixels. Bitmaps are simply pixmaps with a depth of
+// 1. (That is, they are monochrome bitmaps - each pixel can be either
+// on or off).
+// <p>
+// Bitmaps are mostly used as masks when drawing pixmaps, or as a
+// shape for a GDK.Window or a W(Widget)
+// <p>
+#define TWIN ((GdkWindow *)THIS->obj)
+#define GC(X) (get_gdkobject(X, GC))
+
+FUNCTION(copy_area, "function(object,int,int,object,int,int,int,int:object)");
+RETURNS(GDK.Drawable);
+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 drawable, and places the results at xdest,ydest in
+// the drawable 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( TWIN, GC(gc), xd, yd, win, xs, ys, w, h);
+  RETURN_THIS();
+}
+
+FUNCTION(clear, "function(int|void,int|void,int|void,int|void:object)");
+NAME_ARGS(x,y,width,height);
+// Either clears the rectangle defined by the arguments, of if no
+// arguments are specified, the whole drawable.
+{
+  int x=0, y=0, w=0, h=0;
+  if(args==4)
+    get_all_args("clear", args, "%d%d%d%d", &x, &y, &w, &h);
+
+  if(h)
+    gdk_window_clear_area(TWIN, x,y,w,h);
+  else
+    gdk_window_clear(TWIN);
+
+  RETURN_THIS();
+}
+
+FUNCTION(draw_point, "function(object,int,int:object)");
+ARGS(GDK.GC,int,int);
+NAME_ARGS(gc,x,y);
+// img_begin
+// w = GTK.DrawingArea()->set_usize(10,10);
+// delay: g = GDK.GC(w)->set_foreground( GDK.Color(255,0,0) );
+// delay:  for(int x = 0; x<10; x++) w->draw_point(g, x, x);
+// img_end
+{
+  struct object *g;
+  int x, y;
+  get_all_args("draw_point", args, "%o%d%d", &g, &x, &y);
+  
+  gdk_draw_point( TWIN, GC(g), x, y );
+  RETURN_THIS();
+}
+FUNCTION(draw_line, "function(object,int,int,int,int:object)");
+ARGS(GDK.GC,int,int,int,int);
+NAME_ARGS(gc,x1,y1,x2,y2);
+// img_begin
+// w = GTK.DrawingArea()->set_usize(100,100);
+// delay: g = GDK.GC(w)->set_foreground( GDK.Color(255,0,0) );
+// delay:  for(int x = 0; x<10; x++) w->draw_line(g,x*10,0,100-x*10,99);
+// img_end
+{
+  struct object *g;
+  int x, y, x2, y2;
+  get_all_args("draw_line", args, "%o%d%d%d%d", &g, &x, &y, &x2, &y2);
+  
+  gdk_draw_line( TWIN, GC(g), x, y, x2, y2 );
+  RETURN_THIS();
+}
+
+FUNCTION(draw_rectangle, "function(object,int,int,int,int,int:object)");
+ARGS(GDK.GC,int,int,int,int,int);
+NAME_ARGS(gc,filledp,x1,y1,x2,y2);
+// img_begin
+//  w = GTK.DrawingArea()->set_usize(100,100);
+// delay:  g = GDK.GC(w)->set_foreground( GDK.Color(255,0,0) );
+// delay: for(int x = 0; x<10; x++) w->draw_rectangle(g,0,x*10,0,100-x*10,99);
+// img_end
+// img_begin
+// w = GTK.DrawingArea()->set_usize(100,100);
+// delay:   g = GDK.GC(w);
+// delay:  for(int x = 0; x<30; x++) {
+// delay:   g->set_foreground(GDK.Color(random(255),random(255),random(255)) );
+// delay:   w->draw_rectangle(g,1,x*10,0,100-x*10,99);
+// delay: }
+// img_end
+{
+  struct object *g;
+  int f, x, y, x2, y2;
+  get_all_args("draw_rectangle",args, "%o%d%d%d%d%d",&g, &f, &x, &y, &x2, &y2);
+  gdk_draw_rectangle( TWIN, GC(g), f, x, y, x2, y2 );
+  RETURN_THIS();
+}
+
+FUNCTION(draw_arc, "function(object,int,int,int,int,int,int,int:object)");
+ARGS(GDK.GC,int,int,int,int,int,int,int);
+NAME_ARGS(gc,filledp,x1,y1,x2,y2,angle1,angle2);
+// Draws a single circular or elliptical arc.  Each arc is specified
+// by a rectangle and two angles. The center of the circle or ellipse
+// is the center of the rectangle, and the major and minor axes are
+// specified by the width and height.  Positive angles indicate
+// counterclockwise motion, and negative angles indicate clockwise
+// motion. If the magnitude of angle2 is greater than 360 degrees,
+// it is truncated to 360 degrees.
+{
+  struct object *g;
+  int f, x, y, x2, y2, a1, a2;
+  get_all_args("draw_arc",args, "%o%d%d%d%d%d%d%d",&g, &f, &x, &y, &x2, &y2,
+	       &a1, &a2);
+  gdk_draw_arc( TWIN, GC(g), f, x, y, x2, y2, a1, a2 );
+  RETURN_THIS();
+}
+FUNCTION(draw_text, "function(object,object,int,int,string,int|void:object)");
+ARGS(GDK.GC,GDK.Font,int,int,string,int|void);
+NAME_ARGS(gc,font,x,y,text,forcewide);
+// y is used as the baseline for the text.<br>
+// If forcewide is true, the string will be expanded to a wide string
+// even if it is not already one. This is useful when writing text
+// using either unicode or some other 16 bit font.
+{
+  struct object *g,*f;
+  int x, y, force_wide=0;
+  struct pike_string *s;
+  char *swapped;
+  get_all_args("draw_text",args, "%o%o%d%d%W",&g,&f,  &x, &y, &s);
+  if(swapped = get_swapped_string( s,args>5 ))
+  {
+    gdk_draw_text( TWIN,get_gdkobject(f,Font), get_gdkobject(g,GC),
+		   x, y, swapped, s->len<<s->size_shift );
+    free(swapped);
+  } else {
+    gdk_draw_text( TWIN, get_gdkobject(f,Font), get_gdkobject(g,GC),
+		   x, y, s->str, s->len<<s->size_shift );
+  }
+  RETURN_THIS();
+}
+
+FUNCTION(draw_pixmap, "function(object,object,int,int,int,int,int,int:object)");
+ARGS(GDK.GC,GDK.Pixmap,int,int,int,int,int,int);
+NAME_ARGS(gc,pixmap,xsrc,ysrc,xdest,ydest,width,height);
+// Draw the rectangle specified by xsrc,ysrc+width,height from the
+// GDK(Pixmap) at xdest,ydest in the destination drawable
+{
+  struct object *g, *p;
+  int xs, ys, xd, yd, w, h;
+  get_all_args("draw_pixmap",args,"%o%o%d%d%d%d%d%d",
+	       &g,&p,&xs,&ys,&xd,&yd,&w,&h);
+  gdk_draw_pixmap(TWIN,GC(g),get_gdkobject(p,Drawable),xs,ys,xd,yd,w,h);
+  RETURN_THIS();
+}
+
+FUNCTION(draw_bitmap, "function(object,object,int,int,int,int,int,int:object)");
+ARGS(GDK.GC,GDK.Bitmap,int,int,int,int,int,int);
+NAME_ARGS(gc,bitmap,xsrc,ysrc,xdest,ydest,width,height);
+// Draw a GDK(Bitmap) in this drawable.<br>
+// <b>NOTE:</b> This drawable must be a bitmap as well. This will be
+// fixed in GTK 1.3
+{
+  struct object *g, *p;
+  int xs, ys, xd, yd, w, h;
+  get_all_args("draw_pixmap",args,"%o%o%d%d%d%d%d%d",
+	       &g,&p,&xs,&ys,&xd,&yd,&w,&h);
+  /* Hm. gdk_draw_bitmap does not exist? Not that it matters. */
+  gdk_draw_pixmap(TWIN,GC(g),get_gdkobject(p,Drawable),xs,ys,xd,yd,w,h);
+  RETURN_THIS();
+}
+
+FUNCTION(draw_image, "function(object,object,int,int,int,int,int,int:object)");
+ARGS(GDK.GC,GDK.Image,int,int,int,int,int,int);
+NAME_ARGS(gc,image,xsrc,ysrc,xdest,ydest,width,height);
+// Draw the rectangle specified by xsrc,ysrc+width,height from the
+// GDK(Image) at xdest,ydest in the destination drawable
+{
+  struct object *g, *p;
+  int xs, ys, xd, yd, w, h;
+  get_all_args("draw_pixmap",args,"%o%o%d%d%d%d%d%d",
+	       &g,&p,&xs,&ys,&xd,&yd,&w,&h);
+  gdk_draw_image(TWIN,GC(g),get_gdkobject(p,Image),xs,ys,xd,yd,w,h);
+  RETURN_THIS();
+}
+
+FUNCTION(xsize, "function(void:int)");
+// Returns the width of the drawable specified in pixels
+{
+  int s;
+  gdk_window_get_size( TWIN, &s, 0 );
+  push_int( s );
+}
+
+FUNCTION(ysize, "function(void:int)");
+// Returns the height of the drawable specified in pixels
+{
+  int s;
+  gdk_window_get_size( TWIN, 0, &s );
+  push_int( s );
+}
+
+FUNCTION(get_geometry, "function(void:mapping(string:int))");
+// Get width, height position and depth of the drawable as a mapping.
+// <br>
+// ([ "x":xpos, "y":ypos, "width":xsize, "height":ysize, 
+//    "depth":bits_per_pixel ])
+{
+  int x=0, y=0;
+  int w=0, h=0, d=0;
+  gdk_window_get_geometry( TWIN, &x, &y, &w, &h, &d );
+  push_text("x");  push_int(x);
+  push_text("y");  push_int(y);  
+  push_text("width");  push_int(w);
+  push_text("height"); push_int(h);
+  push_text("depth"); push_int(d);
+  f_aggregate_mapping( 10 );
+}
diff --git a/src/post_modules/GTK/source/gdkfont.pre b/src/post_modules/GTK/source/gdkfont.pre
new file mode 100644
index 0000000000000000000000000000000000000000..b7ece6e94e64586e94cfbc43cfa8ce8c89026cc0
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkfont.pre
@@ -0,0 +1,106 @@
+PROGRAM(GdkFont);
+// The GdkFont data type represents a font for drawing on the
+// screen. These functions provide support for loading fonts, and also
+// for determining the dimensions of characters and strings when drawn
+// with a particular font.
+// <p> 
+// Fonts in X are specified by a X Logical Font Description. The
+// following description is considerably simplified. For definitive
+// information about XLFD's see the X reference documentation. A X
+// Logical Font Description (XLFD) consists of a sequence of fields
+// separated (and surrounded by) '-' characters. For example, Adobe
+// Helvetica Bold 12 pt, has the full description: <br>
+// <i> "-adobe-helvetica-bold-r-normal--12-120-75-75-p-70-iso8859-1"</i>
+// <p>
+
+
+//The fields in the XLFD are: 
+// <table>
+// <tr><td> Foundry</td>
+// <td>the company or organization where the font originated.</td></tr>
+// <tr><td> Family</td>
+// <td>the font family (a group of related font designs).</td></tr>
+// <tr><td> Weight</td>
+// <td>A name for the font's typographic weight For example, 'bold' or 'medium').</td></tr>
+// <tr><td> Slant</td>
+// <td>The slant of the font. Common values are 'R' for Roman, 'I' for italoc, and 'O' for oblique.</td></tr>
+// <tr><td> Set Width</td>
+// <td>A name for the width of the font. For example, 'normal' or 'condensed'.</td></tr>
+// <tr><td> Add Style</td>
+// <td>Additional information to distinguish a font from other fonts of the same family.</td></tr>
+// <tr><td> Pixel Size</td>
+// <td>The body size of the font in pixels.</td></tr>
+// <tr><td> Point Size</td>
+// <td>The body size of the font in 10ths of a point. (A point is 1/72.27 inch) </td></tr>
+// <tr><td> Resolution X</td>
+// <td>The horizontal resolution that the font was designed for.</td></tr>
+// <tr><td> Resolution Y</td>
+// <td>The vertical resolution that the font was designed for .</td></tr>
+// <tr><td> Spacing</td>
+// <td>The type of spacing for the font - can be 'p' for proportional, 'm' for monospaced or 'c' for charcell.</td></tr>
+// <tr><td> Average Width</td>
+// <td>The average width of a glyph in the font. For monospaced and charcell fonts, all glyphs in the font have this width</td></tr>
+// <tr><td>Charset Registry</td>
+// <td>                          The registration authority that owns the encoding for the font. Together with the Charset Encoding field, this                        defines the character set for the font.</td></tr>
+// <tr><td>Charset Encoding</td>
+// <td>An identifier for the particular character set encoding.</td></tr>
+// </table>
+// <p>
+// When specifying a font via a X logical Font Description, '*' can be
+// used as a wildcard to match any portion of the XLFD. For instance,
+// the above example could also be specified as
+// <i>"-*-helvetica-bold-r-normal--*-120-*-*-*-*-iso8859-1"</i>
+// <p>
+// It is generally a good idea to use wildcards for any portion of the
+// XLFD that your program does not care about specifically, since that
+// will improve the chances of finding a matching font.
+FUNCTION(create, "function(string|void:void)");
+NAME_ARGS(font_name);
+// Create a new font object. The string is the font XLFD.
+{
+  char *n;
+  if(args)
+  {
+    get_all_args("Gdk.Font", args, "%s", &n);
+    THIS->obj = (void*)gdk_font_load( n );
+    if(!THIS->obj)
+      error("Failed to load font.\n");
+  } else { 
+  }
+}
+FUNCTION(destroy, "function(void:void)");
+// Free the font, called automatically by pike when the object is destroyed.
+{
+  if(THIS->obj)
+    gdk_font_unref( (GdkFont*)THIS->obj );
+}
+
+FUNCTION(text_width, "function(string,int|void:int)")
+NAME_ARGS(text,force_16bitwidestring);
+// Gives the width, in pixels, of the text. If force_wide is true, the 
+// text will be padded or shrunk to 16bit characters, no matter what
+// the original width of the text was. This is useful when the font is 
+// a X 16bit wide font.
+{
+  struct pike_string *s;
+  char *swapped;
+  get_all_args("text_width", args, "%W", &s);
+  if( (swapped = get_swapped_string( s,args>1 )) )
+  {
+    push_int(gdk_text_width((GdkFont*)THIS->obj,
+			    swapped,s->len<<s->size_shift));
+    free(swapped);
+  } else {
+    push_int(gdk_text_width((GdkFont*)THIS->obj,
+			    s->str,s->len<<s->size_shift));
+  }
+}
+
+FUNCTION(char_width, "function(int:int)")
+NAME_ARGS(character);
+// Return the width, in pixels, of the specified character, if
+// rendered with this font. The character can be between 0 and 65535,
+// the character encoding is font specific.
+{
+  push_int(gdk_char_width((GdkFont*)THIS->obj, sp[-args].u.integer));
+}
diff --git a/src/post_modules/GTK/source/gdkgc.pre b/src/post_modules/GTK/source/gdkgc.pre
new file mode 100644
index 0000000000000000000000000000000000000000..81edb61a0905acdf7ea64932cf81e0bdd2b3ef8c
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkgc.pre
@@ -0,0 +1,111 @@
+PROGRAM(GdkGC);
+// A GC, or Graphics Context, is used for most low-level drawing operation.
+// <p>
+// As an example, the foreground color, background color and drawing
+// function is stored in the GC.
+//
+// NOIMG
+FUNCTION(create, "function(object:void)");
+ARGS(GTK.Widget|GDK.Drawable);
+NAME_ARGS(context);
+// The argument is a either a W(Widget) or a GDK(Drawable) in
+// which the gc will be valid.
+{
+  struct object *o;
+  get_all_args("'()", args, "%o", &o);
+  if(get_gdkobject(o, Drawable))
+    THIS->obj = (void *)gdk_gc_new( (GdkWindow*)get_gdkobject(o,Drawable) );
+  else
+    THIS->obj = (void *)gdk_gc_new( GTK_WIDGET(get_gtkobject(o))->window );
+}
+FUNCTION(destoy, "function(void:void)");
+// Free the gc, called automatically by pike when the object is destroyed.
+{
+  gdk_gc_destroy( (GdkGC*)THIS->obj );
+  destruct(fp->current_object);
+}
+FUNCTION(set_foreground, "function(object:object)");
+ARGS(GDK.Color);
+NAME_ARGS(color);
+RETURNS(GDK.GC);
+// Set the foreground to the specified GDK.Color.
+{
+  struct object *o;
+  get_all_args("set_foreground", args, "%o", &o);
+  gdk_gc_set_foreground( (GdkGC*)THIS->obj, get_gdkobject(o, Color));
+  RETURN_THIS();
+}
+FUNCTION(set_background, "function(object:object)");
+ARGS(GDK.Color);
+NAME_ARGS(color);
+RETURNS(GDK.GC);
+// Set the background to the specified GDK.Color.
+{
+  struct object *o;
+  get_all_args("set_background", args, "%o", &o);
+  gdk_gc_set_background( (GdkGC*)THIS->obj, get_gdkobject(o,Color));
+  RETURN_THIS();
+}
+FUNCTION(set_font, "function(object:object)");
+ARGS(GDK.Font);
+NAME_ARGS(font);
+RETURNS(GDK.GC);
+// Set the font to the specified GDK.Font.
+{
+  struct object *o;
+  get_all_args("set_font", args, "%o", &o);
+  gdk_gc_set_font( (GdkGC*)THIS->obj, get_gdkobject(o,Font));
+  RETURN_THIS();
+}
+FUNCTION(set_clip_origin, "function(int,int:object)");
+NAME_ARGS(x,y);
+RETURNS(GDK.GC);
+// Set the clip mask origin to the specified point.
+{
+  int x, y;
+  get_all_args("set_clip_origin", args, "%d%d", &x, &y);
+  gdk_gc_set_clip_origin((GdkGC*)THIS->obj, x, y );
+  RETURN_THIS();
+}
+
+FUNCTION(set_clip_mask, "function(void|object:object)");
+ARGS(GDK.Bitmap);
+NAME_ARGS(mask);
+RETURNS(GDK.GC);
+// Set the clip mask to the specified GDK.Bitmap
+{
+  if (args == 1)
+  {
+    struct object *o;
+    get_all_args("set_clip_mask", args, "%o", &o);
+    gdk_gc_set_clip_mask( (GdkGC*)THIS->obj, get_gdkobject(o,Bitmap));
+  } else
+    gdk_gc_set_clip_mask( (GdkGC*)THIS->obj, 0);
+
+  RETURN_THIS();
+}
+
+FUNCTION(set_function, "function(int:object)");
+NAME_ARGS(fun);
+RETURNS(GDK.GC);
+// Set the function to the specified one. One of GDK.Xor,
+// GDK.Invert and GDK.Copy.
+{
+  int a;
+  get_all_args("set_function", args, "%d", &a);
+  gdk_gc_set_function( (GdkGC*)THIS->obj, a);
+  RETURN_THIS();
+}
+
+FUNCTION(set_subwindow, "function(int:object)");
+NAME_ARGS(draw_on_subwindows);
+RETURNS(GDK.GC);
+// If set, anything drawn with this GC will draw on subwindows as well
+// as the window in which the drawing is done.
+{
+  int a;
+  get_all_args("set_subwindow", args, "%d", &a);
+  gdk_gc_set_subwindow( (GdkGC*)THIS->obj, a );
+  RETURN_THIS();
+}
+/* TODO: a lot of functions left.. */
diff --git a/src/post_modules/GTK/source/gdkimage.pre b/src/post_modules/GTK/source/gdkimage.pre
new file mode 100644
index 0000000000000000000000000000000000000000..3ecf4fbd63e722c383717bee077a85544b5846dd
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkimage.pre
@@ -0,0 +1,152 @@
+PROGRAM(GdkImage);
+// A gdk (low level) image.
+// Mainly used for W(Image) objects.
+//
+// NOIMG
+FUNCTION(create, "function(int|void:void)");
+NAME_ARGS(fast_mode);
+// Create a new	GDK.Image object. The argument is either 0, which indicates that
+// you want a 'slow' image. If you use '1', you indicate that you want a 'fast'
+// image. Fast images are stored in shared memory, and thus are not sent over
+// any network. But please limit your usage of fast images, they use up 
+// a possibly limited system resource set. See the man page for shmget(2)
+// for more information on the limits on shared segments on your system.
+//<p>
+// A 'fast' image will automatically revert back to 'slow' mode if no shared
+// memory is available.
+{
+  THIS->extra_int = GDK_IMAGE_NORMAL;
+  if(args && sp[-1].u.integer)
+    THIS->extra_int = GDK_IMAGE_FASTEST;
+/* Do not add one extra ref for the internal gdk object..*/
+/*  add_ref(fp->current_object); */
+}
+FUNCTION(destroy, "function(void:void)");
+// Destructor. Destroys the image. Automatically called by pike when the object
+// is destructed.
+{
+  if(THIS->obj)
+    gdk_image_destroy( (void *)THIS->obj );
+  THIS->obj = 0;
+}
+
+#define HEADER "P6\n%d %d\n255\n"
+#define HEADER_SIZE 20 
+
+FUNCTION(get_pnm, "function(void:string)")
+// Returns the data in the image as a pnm object.
+// Currently, this is always a P6 (true color raw) image.
+// This could change in the future. To get a pike image object
+// do 'Image.PNM.decode( gdkimage->get_pnm() )'
+{
+  GdkImage *i = (GdkImage *)THIS->obj;
+  char *res, *p;
+  char header[100];
+  int x, y, len;
+
+  sprintf(header, HEADER, i->width, i->height );
+  len = strlen(header)+i->width*i->height*3;
+  p = res = malloc(len);
+  strcpy(res, header);
+  p+=strlen(header);
+  
+  for(y=0; y<i->height; y++)
+    for(x=0; x<i->width; x++)
+    {
+      unsigned int pi = gdk_image_get_pixel( i, x, y );
+      struct my_pixel pix = pgtk_pixel_from_xpixel( pi, i );
+      /*      fprintf(stderr, "%d,%d\n", x, y); */
+      (*p++) = pix.r;
+      (*p++) = pix.g;
+      (*p++) = pix.b;
+    }
+  push_string(make_shared_binary_string(res,len));
+}
+
+FUNCTION(grab, "function(object,int,int,int,int:object)");
+ARGS(GTK.Widget,int,int,int,int);
+RETURNS(GDK.Image);
+NAME_ARGS(widget,xoffset,yoffset,width,height);
+// Call this function to grab a portion of a widget (argument 1) to the image.
+// Grabbing non-toplevel widgets may produce unexpected results.
+// To get the size of a widget use -&gt;xsize() and -&gt;ysize().
+// To get the offset of the upper left corner of the widget, relative to it's
+// X-window (this is what you want for the offset arguments), use
+// -&gt;xoffset() and -&gt;yoffset().
+{
+  GdkWindow *win = NULL;
+  struct object *o;
+  int x, y, w, h;
+
+  get_all_args("grab", args, "%o%d%d%d%d", &o, &x, &y, &w, &h);
+
+  if(!((win=get_gdkobject( o, Drawable )))
+     && get_pgtkobject( o, pgtk_widget_program))
+    win = GTK_WIDGET(get_pgtkobject( o, pgtk_widget_program))->window;
+
+  if(!win)
+    error("This is not a window, and this widget have a window\n");
+
+  if(THIS->obj)
+    gdk_image_destroy( (void *)THIS->obj );
+
+  THIS->obj = (void *)gdk_image_get( win, x, y, w, h );
+
+  RETURN_THIS();
+}
+
+FUNCTION(set, "function(object|int,void|int:object)");
+// Call this to set this image to either the contents of a pike image
+// or a blank image of a specified size.
+RETURNS(GDK.Image);
+ARGS(Image.image|int,void|int);
+NAME_ARGS(image|xsize,void|ysize);
+{
+  struct object *img;
+
+  if(args == 1)
+  {
+    get_all_args("init", args, "%o", &img);
+    /* Might throw an error!*/
+    THIS->obj = (void *)gdkimage_from_pikeimage( img, THIS->extra_int, 
+						 (void *)THIS->obj );
+  } else {
+    int x, y;
+    get_all_args("gdkImage", args, "%d%d", &x, &y);
+    if(THIS->obj)
+      gdk_image_destroy( (void *)THIS->obj );
+    THIS->obj = (void *)gdk_image_new(THIS->extra_int, 
+				      gdk_visual_get_system(),
+				      x, y);
+    if(!THIS->obj)
+      error("Failed to create gdkImage from size.\n");
+  }
+  RETURN_THIS();
+}
+
+FUNCTION(get_pixel, "function(int,int:int)");
+NAME_ARGS(x,y);
+// Get the pixel value of a pixel as a X-pixel value.
+// It is usualy not very easy to convert this value to a
+// rgb triple. See get_pnm.
+{
+  int x, y;
+  get_all_args("get_pixel", args, "%d%d", &x, &y);
+  if(!THIS->obj) error("No image.\n");
+  pop_n_elems(args);
+  push_int( gdk_image_get_pixel( (void *)THIS->obj, x, y ) );
+}
+FUNCTION(set_pixel, "function(int,int,int:object)")
+NAME_ARGS(x,y,pixel);
+// Arguments: x,y,color
+// Set the pixel value of a pixel. Please note that the color argument
+// is a X-pixel value, which is not easily gotten from a RGB color.
+// See get_pixel and set.
+{
+  int x, y, to;
+  get_all_args("set_pixel", args, "%d%d%d", &x, &y, &to);
+  if(!THIS->obj) error("No image.\n");
+  gdk_image_put_pixel( (void *)THIS->obj, x, y, to );
+  RETURN_THIS();
+}
+
diff --git a/src/post_modules/GTK/source/gdkpixmap.pre b/src/post_modules/GTK/source/gdkpixmap.pre
new file mode 100644
index 0000000000000000000000000000000000000000..a9327488fe5dbec49b30e13561f5a56cb6aa88d9
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkpixmap.pre
@@ -0,0 +1,88 @@
+PROGRAM(GdkPixmap);
+INHERIT(GdkDrawable);
+// This class creates a GDK.Pixmap from either an GDK.Image or
+// Image.image object.  <p> The GDK.Pixmap object can be used in a lot
+// of different GTK widgets.  The most notable is the W(Pixmap)
+// widget.
+//
+// NOIMG
+GdkImage *pgtk_pixmap_setup( struct object *o, int *free)
+{
+  if(get_gdkobject( o, Image ))
+  {
+    return get_gdkobject( o, Image );
+  }
+  else
+  {
+    *free=1;
+    return gdkimage_from_pikeimage( o, GDK_IMAGE_FASTEST, 0 );
+  }
+}
+
+void pgtk__pixmap_draw( GdkImage *i )
+{
+  GdkGC *gc;
+  if(THIS->extra_data)
+    gc = THIS->extra_data;
+  else
+    THIS->extra_data = gc = gdk_gc_new( (GdkWindow *)THIS->obj );
+  gdk_draw_image( (GdkWindow *)THIS->obj, gc, i, 0, 0, 0, 0,
+		  i->width, i->height);
+}
+
+FUNCTION(create, "function(object:void)")
+ARGS(object(GDK.Image)|object(Image.image));
+NAME_ARGS(image);
+// Create a new GDK.Pixmap object. 
+// Argument is a GDK.Image object or a Image.image object
+{
+  GdkImage *i;
+  int f = 0;
+  struct object *o;
+  if(THIS->obj) 
+    error("Pixmap already initialized\n");
+
+  get_all_args("create", args, "%o", &o );
+  i = pgtk_pixmap_setup( o, &f );
+
+  THIS->obj = (void *)gdk_pixmap_new( 0, i->width, i->height, i->depth );
+  if(!THIS->obj) 
+  {
+    if(f) gdk_image_destroy( i );
+    error("Failed to create pixmap.\n");
+  }
+  pgtk__pixmap_draw( i );
+  if(f) gdk_image_destroy( i );
+}
+
+FUNCTION(set, "function(object:object)");
+RETURNS(GDK.Image);
+ARGS(object(GDK.Image)|object(Image.image));
+NAME_ARGS(image);
+// Argument is a GDK.Image object or an Image.image object.
+// It is much faster to use an gdkImage object, especially one 
+// allocated in shared memory. This is only an issue if you are
+// going to change the contents of the pixmap often, toggling between
+// a small number of images.
+{
+  struct object *o;
+  int f = 0;
+  GdkImage *i;
+  get_all_args("set", args, "%o", &o );
+  pgtk__pixmap_draw( i=pgtk_pixmap_setup( o, &f ) );
+  if(f) gdk_image_destroy( i );
+
+  RETURN_THIS();
+}
+
+FUNCTION(destroy, "function(void:void)");
+// Destructor. Destroys the pixmap.
+{
+  if(THIS->obj)
+    gdk_pixmap_unref( (void *)THIS->obj );
+  THIS->obj = 0;
+
+  if(THIS->extra_data)
+    gdk_gc_destroy( (void *)THIS->extra_data );
+  THIS->extra_data = 0;
+}
diff --git a/src/post_modules/GTK/source/gdkrectangle.pre b/src/post_modules/GTK/source/gdkrectangle.pre
new file mode 100644
index 0000000000000000000000000000000000000000..251ae39cb09bd318289786b82adfed168d71972c
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkrectangle.pre
@@ -0,0 +1,62 @@
+PROGRAM(GdkRectangle);
+FUNCTION(create, "function(int,int,int,int:void)");
+NAME_ARGS(x,y,width,height);
+// Create a new rectangle
+// 
+// NOIMG
+{
+  GdkRectangle *r;
+  THIS->obj = (void *)(r=malloc(sizeof(GdkRectangle)));
+  get_all_args( "GDK.Rectangle", args, "%d%d%d%d", &r->x, &r->y, 
+		&r->width, &r->height );
+}
+
+FUNCTION(set, "function(int,int,int,int:object)");
+RETURNS(GDK.Rectangle);
+NAME_ARGS(x,y,width,height);
+// Set the upper left corner and the size of the rectangle.
+{
+  GdkRectangle *r = (GdkRectangle *)THIS->obj;
+  get_all_args( "GDK.Rectangle->set", args, "%d%d%d%d", &r->x, &r->y, 
+		&r->width, &r->height );
+  RETURN_THIS();
+}
+
+FUNCTION(cast, "function(string:mixed)");
+NAME_ARGS(type);
+// Normally used like (mapping)rectangle or (array)rectangle.
+{
+  char *type;
+  GdkRectangle *r = (GdkRectangle *)THIS->obj;
+  get_all_args( "cast", args, "%s", &type );
+
+  if(!strcmp(type, "mapping"))
+  {
+    pop_n_elems(args);
+    push_text( "x" );
+    push_int( r->x );
+    push_text( "y" );
+    push_int( r->y );
+    push_text( "width" );
+    push_int( r->width );
+    push_text( "height" );
+    push_int( r->height );
+    f_aggregate_mapping( 8 );
+  } else if(!strcmp(type, "array")) {
+    pop_n_elems(args);
+    push_int( r->x );
+    push_int( r->y );
+    push_int( r->width );
+    push_int( r->height );
+    f_aggregate( 4 );
+  } else {
+    error("Cannot cast to %s.\n", type );
+  }
+}
+
+FUNCTION(destroy, "function(void:void)")
+{
+  free(THIS->obj);
+}
+
+/* TODO: gdk_region_polygon (GdkPoint    *points, ...*/
diff --git a/src/post_modules/GTK/source/gdkregion.pre b/src/post_modules/GTK/source/gdkregion.pre
new file mode 100644
index 0000000000000000000000000000000000000000..12b614e1dc33a3742cadfcd8a495592e8a1f521c
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkregion.pre
@@ -0,0 +1,187 @@
+PROGRAM(GdkRegion);
+FUNCTION(create, "function(void:void)");
+// Create a new (empty) region
+// 
+// NOIMG
+{
+  THIS->obj = (void *)gdk_region_new();
+}
+FUNCTION(destroy, "function(void:void)");
+{
+  gdk_region_destroy((GdkRegion *)THIS->obj);
+}
+
+FUNCTION(equal, "function(object:int)");
+ARGS(GDK.Region);
+NAME_ARGS(victim);
+// Return true if the region used as an argument is equal to the current region.
+// Also available as a==b when a is a region.
+{
+  struct object *o;
+  GdkRegion *r;
+  get_all_args( "equal", args, "%o", &o);
+  r = get_gdkobject( o, Region );
+  if(!r)
+  {
+    pop_n_elems(args);
+    push_int(0);
+    return;
+  } else {
+    int eq = gdk_region_equal( (GdkRegion *)THIS->obj, r );
+    pop_n_elems(args);
+    push_int(eq);
+  }
+}
+
+FUNCTION(point_in, "function(int,int:int)");
+NAME_ARGS(x,y);
+// Returns true if the given point resides in the given region
+{
+  int x, y;
+  get_all_args( "point_in", args, "%d%d", &x, &y );
+  pop_n_elems(args);
+  push_int( gdk_region_point_in( (GdkRegion *)THIS->obj, x, y ) );
+}
+
+FUNCTION(rect_in, "function(object:int)");
+ARGS(GDK.Rectangle);
+NAME_ARGS(rectangle);
+// Returns true if the given rectangle resides inside the given region
+{
+  struct object *o;
+  GdkRectangle *r;
+  get_all_args( "rect_in", args, "%o", &o );
+  if(!(r = get_gdkobject( o, Rectangle )))
+  {
+    error("Bad argument 1 to GDK.rect_in( GDK.Rectangle r )\n");
+  } else {
+    int b = gdk_region_rect_in((GdkRegion *)THIS->obj,  r);
+    pop_n_elems(args);
+    push_int( b );
+  }
+}
+
+FUNCTION(offset, "function(int,int:object)");
+RETURNS(GDK.Region);
+NAME_ARGS(dx,dy);
+RETURNS(GDK.Region);
+// Offset(move) the region by dx,dy pixels.
+{
+  int dx, dy;
+  get_all_args( "offset", args, "%d%d", &dx, &dy );
+  gdk_region_offset( (GdkRegion *)THIS->obj, dx, dy );
+  RETURN_THIS();
+}
+
+
+FUNCTION(shrink, "function(int,int:object)");
+RETURNS(GDK.Region);
+NAME_ARGS(dx,dy);
+RETURNS(GDK.Region);
+// reduces the size of a region by a
+// specified amount.  Positive values shrink the size of the
+// region, and negative values expand the region.
+{
+  int dx, dy;
+  get_all_args( "shrink", args, "%d%d", &dx, &dy );
+  gdk_region_shrink( (GdkRegion *)THIS->obj, dx, dy );
+  RETURN_THIS();
+}
+
+FUNCTION(union, "function(object:object)");
+ARGS(GDK.Region|GDK.Rectangle);
+RETURNS(GDK.Region);
+NAME_ARGS(with);
+// Computes the union of the given rectangle or region and the region.
+// Also available as region | rectangle, region | region, region + region 
+// and region + rectangle. 
+{
+  struct object *o;
+  void *v;
+  GdkRegion *r;
+  get_all_args( "union", args, "%o", &o );
+  if( (v = get_gdkobject(o, Rectangle )) )
+    r = gdk_region_union_with_rect( (GdkRegion *)THIS->obj, v);
+  else if( (v=get_gdkobject(o, Region )) )
+    r = gdk_regions_union( (GdkRegion *)THIS->obj, v);
+  else
+    error("Bad argument to union: Not Region or Rectangle\n");
+  pop_n_elems(args);
+  o = low_clone( pgtk_GdkRegion_program );
+  call_c_initializers( o );
+  ((struct object_wrapper *)o->storage)->obj = (void *)r;
+  push_object( o );
+  return;
+}
+
+FUNCTION(intersect, "function(object:object)");
+ARGS(GDK.Region);
+RETURNS(GDK.Region);
+NAME_ARGS(with);
+// Computes the intersection of the given region and the region.
+// Also available as region & region
+{
+  struct object *o;
+  void *v;
+  GdkRegion *r;
+  get_all_args( "intersect", args, "%o", &o );
+  if( (v=get_gdkobject(o, Region )) ) {
+    r = gdk_regions_union( (GdkRegion *)THIS->obj, v);
+  } else {
+    error("Bad argument to intersect: Not a GDK.Region object\n");
+  }
+  pop_n_elems(args);
+  o = low_clone( pgtk_GdkRegion_program );
+  call_c_initializers( o );
+  ((struct object_wrapper *)o->storage)->obj = (void *)r;
+  push_object( o );
+  return;
+}
+
+FUNCTION(subtract, "function(object:object)");
+ARGS(GDK.Region);
+RETURNS(GDK.Region);
+NAME_ARGS(with);
+// Computes the difference of the given region and the region.
+// Also available as region - region
+{
+  struct object *o;
+  void *v;
+  GdkRegion *r;
+  get_all_args( "subtract", args, "%o", &o );
+  if( (v=get_gdkobject(o, Region )) ) {
+    r = gdk_regions_subtract( (GdkRegion *)THIS->obj, v);
+  } else {
+    error("Bad argument to subtract: Not a GDK.Region object\n");
+  }
+  pop_n_elems(args);
+  o = low_clone( pgtk_GdkRegion_program );
+  call_c_initializers( o );
+  ((struct object_wrapper *)o->storage)->obj = (void *)r;
+  push_object( o );
+  return;
+}
+
+FUNCTION(xor, "function(object:object)");
+ARGS(GDK.Region);
+RETURNS(GDK.Region);
+NAME_ARGS(with);
+// Computes the exlusive or of the given region and the region.
+// Also available as region ^ region
+{
+  struct object *o;
+  void *v;
+  GdkRegion *r;
+  get_all_args( "xor", args, "%o", &o );
+  if( (v=get_gdkobject(o, Region )) ) {
+    r = gdk_regions_xor( (GdkRegion *)THIS->obj, v);
+  } else {
+    error("Bad argument to xor: Not a GDK.Region object\n");
+  }
+  pop_n_elems(args);
+  o = low_clone( pgtk_GdkRegion_program );
+  call_c_initializers( o );
+  ((struct object_wrapper *)o->storage)->obj = (void *)r;
+  push_object( o );
+  return;
+}
diff --git a/src/post_modules/GTK/source/gdkwindow.pre b/src/post_modules/GTK/source/gdkwindow.pre
new file mode 100644
index 0000000000000000000000000000000000000000..1631c127488f6c70bd2c4b7d9d08b40de1576a1b
--- /dev/null
+++ b/src/post_modules/GTK/source/gdkwindow.pre
@@ -0,0 +1,564 @@
+PROGRAM(GdkWindow);
+// a GDK.Window object.
+//
+// NOIMG
+INHERIT(GdkDrawable);
+FUNCTION(create, "function(mixed...:void)");
+ARGS(int|object,void|mapping);
+NAME_ARGS(XWindowID|parent,void|atrributes);
+// Not for non-experts. I promise.
+{
+  if(sp[-args].type == T_INT)
+  {
+    int id;
+    get_all_args( "GdkWindow", args, "%d", &id );
+    THIS->obj = (void *)gdk_window_foreign_new( id );
+    if( !THIS->obj )
+      error("The window with id 0x%x does not exist\n", id);
+  } else if(sp[-args].type == T_OBJECT) {
+    struct object *parent;
+    struct mapping *m;
+    GdkWindowAttr attrs;
+    long mask = 0;
+    MEMSET(&attrs, 0, sizeof(attrs));
+    get_all_args( "GdkWindow", args, "%o%m", &parent, &m );
+
+#define GET_ARG(x,y,z) pgtk_get_mapping_arg( m, #x, y, z, &attrs.x, &mask, sizeof(attrs.x))
+
+    GET_ARG(title, T_STRING, GDK_WA_TITLE);
+    GET_ARG(x, T_INT, GDK_WA_X);
+    GET_ARG(y, T_INT, GDK_WA_Y);
+    GET_ARG(width, T_INT, 0);
+    GET_ARG(height, T_INT, 0);
+    GET_ARG(window_type, T_INT, 0);
+    GET_ARG(wmclass_name, T_STRING, 0);
+    GET_ARG(wmclass_class, T_STRING, 0);
+    GET_ARG(override_redirect, T_INT, GDK_WA_NOREDIR);
+    
+    THIS->obj=(void *)gdk_window_new(get_gdkobject(parent,Window),&attrs,mask);
+  }
+}
+
+FUNCTION(is_viewable, "function(void:int)");
+// Return 1 if the window is mapped.
+{
+  pop_n_elems(args);
+  push_int(gdk_window_is_viewable( (GdkWindow *)THIS->obj ));
+}
+
+FUNCTION(is_visible, "function(void:int)");
+// Return 1 if the window, or a part of the window, is visible right now.
+{
+  pop_n_elems(args);
+  push_int(gdk_window_is_visible( (GdkWindow *)THIS->obj ));
+}
+
+FUNCTION(set_cursor, "function(int:object)");
+// Change the window cursor.<table border=0 cellpadding=3 cellspacing=0>
+// CURS(GDK.Arrow)
+// CURS(GDK.BasedArrowDown)
+// CURS(GDK.BasedArrowUp)
+// CURS(GDK.Boat)
+// CURS(GDK.Bogosity)
+// CURS(GDK.BottomLeftCorner)
+// CURS(GDK.BottomRightCorner)
+// CURS(GDK.BottomSide)
+// CURS(GDK.BottomTee)
+// CURS(GDK.BoxSpiral)
+// CURS(GDK.CenterPtr)
+// CURS(GDK.Circle)
+// CURS(GDK.Clock)
+// CURS(GDK.CoffeeMug)
+// CURS(GDK.Cross)
+// CURS(GDK.CrossReverse)
+// CURS(GDK.Crosshair)
+// CURS(GDK.DiamondCross)
+// CURS(GDK.Dot)
+// CURS(GDK.Dotbox)
+// CURS(GDK.DoubleArrow)
+// CURS(GDK.DraftLarge)
+// CURS(GDK.DraftSmall)
+// CURS(GDK.DrapedBox)
+// CURS(GDK.Exchange)
+// CURS(GDK.Fleur)
+// CURS(GDK.Gobbler)
+// CURS(GDK.Gumby)
+// CURS(GDK.Hand1)
+// CURS(GDK.Hand2)
+// CURS(GDK.Heart)
+// CURS(GDK.Icon)
+// CURS(GDK.IronCross)
+// CURS(GDK.LeftPtr)
+// CURS(GDK.LeftSide)
+// CURS(GDK.LeftTee)
+// CURS(GDK.Leftbutton)
+// CURS(GDK.LlAngle)
+// CURS(GDK.LrAngle)
+// CURS(GDK.Man)
+// CURS(GDK.Middlebutton)
+// CURS(GDK.Mouse)
+// CURS(GDK.Pencil)
+// CURS(GDK.Pirate)
+// CURS(GDK.Plus)
+// CURS(GDK.QuestionArrow)
+// CURS(GDK.RightPtr)
+// CURS(GDK.RightSide)
+// CURS(GDK.RightTee)
+// CURS(GDK.Rightbutton)
+// CURS(GDK.RtlLogo)
+// CURS(GDK.Sailboat)
+// CURS(GDK.SbDownArrow)
+// CURS(GDK.SbHDoubleArrow)
+// CURS(GDK.SbLeftArrow)
+// CURS(GDK.SbRightArrow)
+// CURS(GDK.SbUpArrow)
+// CURS(GDK.SbVDoubleArrow)
+// CURS(GDK.Shuttle)
+// CURS(GDK.Sizing)
+// CURS(GDK.Spider)
+// CURS(GDK.Spraycan)
+// CURS(GDK.Star)
+// CURS(GDK.Target)
+// CURS(GDK.Tcross)
+// CURS(GDK.TopLeftArrow)
+// CURS(GDK.TopLeftCorner)
+// CURS(GDK.TopRightCorner)
+// CURS(GDK.TopSide)
+// CURS(GDK.TopTee)
+// CURS(GDK.Trek)
+// CURS(GDK.UlAngle)
+// CURS(GDK.Umbrella)
+// CURS(GDK.UrAngle)
+// CURS(GDK.Watch)
+// CURS(GDK.Xterm)
+// </table>
+NAME_ARGS(cursor_type);
+{
+  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( (GdkWindow *)THIS->obj, 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(  (GdkWindow *)THIS->obj,
+                          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();
+}
+
+FUNCTION(shape_combine_mask, "function(object,int,int:object)");
+RETURNS(GDK.Window);
+ARGS(GDK.Bitmap,int,int);
+NAME_ARGS(mask,xoffset,yoffset);
+// Set the shape of the widget, or, rather, it's window, to that of
+// the supplied bitmap.
+{
+  struct object *m;
+  int x, y;
+  get_all_args("shape_combine", args, "%o%d%d", &m, &x, &y);
+  gdk_window_shape_combine_mask( (GdkWindow *)THIS->obj, get_gdkobject(m,Bitmap), x, y);
+  RETURN_THIS();
+}
+
+GList*
+pgdk_window_get_children (GdkWindow *window)
+{
+  GdkWindowPrivate *private;
+  GdkWindow *child;
+  GList *children;
+  Window root;
+  Window parent;
+  Window *xchildren;
+  unsigned int nchildren;
+  unsigned int i;
+
+  g_return_val_if_fail (window != NULL, NULL);
+
+  private = (GdkWindowPrivate*) window;
+  if (private->destroyed)
+    return NULL;
+
+  XQueryTree (private->xdisplay, private->xwindow,
+	      &root, &parent, &xchildren, &nchildren);
+
+  children = NULL;
+
+  if (nchildren > 0)
+    {
+      for (i = 0; i < nchildren; i++)
+	{
+	  child = gdk_window_lookup (xchildren[i]);
+	  if(!child)
+	    child = gdk_window_foreign_new (xchildren[i]);
+          if (child)
+            children = g_list_prepend (children, child);
+	}
+
+      XFree (xchildren);
+    }
+
+  return children;
+}
+
+FUNCTION(children, "function(void:array(object))");
+RETURNS(array(GDK.Window));
+// Returns an array of GDK.Window objects.
+{
+  GList *l;
+  int n = 0;
+
+  l = pgdk_window_get_children( (GdkWindow *)THIS->obj );
+  
+  while(l)
+  {
+    struct object *o;
+    o = low_clone( pgtk_GdkWindow_program );
+    call_c_initializers( o );
+    /* ugly...*/
+    ((struct object_wrapper *)o->storage)->obj=(void *)l->data;
+    push_object( o );
+    n++;
+    l = l->next;
+  }
+  pop_n_elems(args);
+  f_aggregate(n);
+}
+
+FUNCTION(set_events, "function(int:object)");
+NAME_ARGS( events );
+// events is a bitwise or of one or more of the following constants: 
+// 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
+{
+  int a;
+  get_all_args( "set_events", args, "%d", &a );
+  gdk_window_set_events( (GdkWindow *)THIS->obj, a );
+  RETURN_THIS();
+}
+
+FUNCTION(set_icon, "function(object|void,object|void,object|void:object)");
+RETURNS(GDK.Window);
+NAME_ARGS(window,pixmap,mask);
+ARGS(GDK.Pixmap,GDK.Bitmap,GDK.Window);
+// Set the icon to the specified image (with mask) or the specified
+// GDK.Window.  It is up to the window manager to display the icon.
+// Most window manager handles window and pixmap icons, but only a few
+// can handle the mask argument. If you want a shaped icon, the only
+// safe bet is a shaped window.
+
+{
+  GdkPixmap *p = NULL;
+  GdkBitmap *m = NULL;
+  GdkWindow *w = NULL;
+  switch(args)
+  {
+   default:
+   case 3:
+     if(sp[-args+2].type == T_OBJECT)
+       w = get_gdkobject(sp[-args+2].u.object , Window );
+   case 2:
+     if(sp[-args+1].type == T_OBJECT)
+       m = get_gdkobject(sp[-args+1].u.object , Bitmap );
+   case 1:
+     if(sp[-args].type == T_OBJECT)
+       p = get_gdkobject(sp[-args].u.object , Pixmap );
+     /*    case 0:
+      * Some commercial CC breaks with empty case.
+      * // David
+      */ 
+  }
+  gdk_window_set_icon((GdkWindow *)THIS->obj, w, p, m );
+  RETURN_THIS();
+}
+
+
+FUNCTION(set_icon_name, "function(string:object)")
+NAME_ARGS(icon_name);
+RETURNS(GDK.Window);
+// Set the icon name to the specified string.
+{
+  gchar *t;
+  get_all_args("set_icon_name", args, "%s", &t);
+  gdk_window_set_icon_name( (GdkWindow *)THIS->obj, t );
+  RETURN_THIS();
+}
+
+FUNCTION(raise, "function(void:object)");
+RETURNS(GDK.Window);
+// Raise this window if the window manager allows that.
+{
+  gdk_window_raise( (GdkWindow *)THIS->obj );
+  RETURN_THIS();
+}
+
+FUNCTION(move_resize, "function(int,int,int,int:object)");
+NAME_ARGS(x,y,w,h);
+RETURNS(GDK.Window);
+// Move and resize the window in one call.
+{
+  gint x, y, w, h;
+  get_all_args( "move_resize", args, "%d%d%d%d", &x, &y, &w, &h );
+  gdk_window_move_resize( (GdkWindow *)THIS->obj, x,y,w,h );
+  RETURN_THIS();
+}
+
+FUNCTION(get_geometry, "function(void:mapping)");
+RETURNS(mapping(string:int));
+// Returns ([ "x":xpos, "y":ypos, "width":width, "height":height, "depth":bits_per_pixel ])
+{
+  gint x, y, w, h, d;
+  gdk_window_get_geometry( (GdkWindow *)THIS->obj, &x, &y, &w, &h, &d );
+  push_constant_text( "x" ); push_int(x);
+  push_constant_text( "y" ); push_int(y);
+  push_constant_text( "width" );  push_int(w);
+  push_constant_text( "height" );  push_int(h);
+  push_constant_text( "depth" ); push_int(d);
+  f_aggregate_mapping( 10 );
+}
+
+
+FUNCTION(lower, "function(void:object)")
+RETURNS(GDK.Window);
+// Lower this window if the window manager allows that.
+{
+  gdk_window_lower( (GdkWindow *)THIS->obj );
+  RETURN_THIS();
+}
+
+
+/* gint */
+/* pgdk_property_get (GdkWindow   *window, */
+/* 		   GdkAtom      property, */
+/* 		   GdkAtom      type, */
+/* 		   gulong       offset, */
+/* 		   gulong       length, */
+/* 		   gint         pdelete, */
+/* 		   GdkAtom     *actual_property_type, */
+/* 		   gint        *actual_format_type, */
+/* 		   gint        *actual_length, */
+/* 		   guchar     **data) */
+/* { */
+/*   Display *xdisplay; */
+/*   Window xwindow; */
+/*   Atom ret_prop_type; */
+/*   gint ret_format; */
+/*   gulong ret_nitems; */
+/*   gulong ret_bytes_after; */
+/*   gulong ret_length; */
+/*   guchar *ret_data; */
+
+/*   if (window) */
+/*     { */
+/*       GdkWindowPrivate *private; */
+
+/*       private = (GdkWindowPrivate*) window; */
+/*      if (private->destroyed) */
+/* 	return FALSE; */
+
+/*       xdisplay = private->xdisplay; */
+/*       xwindow = private->xwindow; */
+/*     } */
+/*   else */
+/*     { */
+/*       xdisplay = gdk_display; */
+/*       xwindow = gdk_root_window; */
+/*     } */
+
+/*   XGetWindowProperty (xdisplay, xwindow, property, */
+/* 		      offset, (length + 3) / 4, pdelete, */
+/* 		      type, &ret_prop_type, &ret_format, */
+/* 		      &ret_nitems, &ret_bytes_after, */
+/* 		      &ret_data); */
+
+/*   if ((ret_prop_type == None) && (ret_format == 0)) { */
+/*     return FALSE; */
+/*   } */
+
+/*   if (actual_property_type) */
+/*     *actual_property_type = ret_prop_type; */
+/*   if (actual_format_type) */
+/*     *actual_format_type = ret_format; */
+/*   if (data) */
+/*     *data = ret_data; */
+/*   if(actual_length) */
+/*     *actual_length = ret_nitems; */
+/*   return TRUE; */
+/* } */
+
+FUNCTION(get_property, "function(object,int,int,int:mapping)");
+ARGS( GDK.Atom, int|void, int|void );
+NAME_ARGS( property, offset, delete_when_done );
+// Returns the value (as a string) of the specified property.
+// The arguments are: 
+// <p>
+// property: The property atom, as an example GDK.Atom.__SWM_VROOT<br>
+// offset (optional): The starting offset, in elements<br>
+// delete_when_done (optional): If set, the property will be deleted when it has
+// been fetched.<br>
+// <p>
+// Example usage: Find the 'virtual' root window (many window managers
+// put large windows over the screen)
+// <p>
+// <pre>
+// &nbsp; GDK.Window root = GTK.root_window();
+// &nbsp; array maybe=root->children()->
+// &nbsp;             get_property(GDK.Atom.__SWM_VROOT)-({0});
+// &nbsp; if(sizeof(maybe)) 
+// &nbsp;   root=GDK.Window( maybe[0]->data[0] );
+// </pre>
+{
+  guchar *retdata;
+  GdkAtom actual_property_type;
+  int actual_format_type, actual_length;
+  struct object *o;
+  int offset = 0;
+  int delete_when_done = 0;
+  if(args == 3)
+    get_all_args( "get_property", args, "%o%d%d", &o, &offset, &delete_when_done );
+  else if(args == 2)
+    get_all_args( "get_property", args, "%o%d", &o, &offset);
+  else
+    get_all_args( "get_property", args, "%o", &o);
+
+
+  if(gdk_property_get( (GdkWindow *)THIS->obj,
+                       get_gdkatom(o),
+                       AnyPropertyType,
+                       offset,
+                       1024*1024*1024,
+                       delete_when_done,
+                       &actual_property_type,
+                       &actual_format_type,
+                       &actual_length,
+                       &retdata ))
+  {
+    struct object *o;
+    pop_n_elems(args);
+    push_text( "type" );
+    push_text( gdk_atom_name( actual_property_type ) );
+    push_text( "width" );
+    push_int( actual_format_type );
+    push_text( "data" );
+    switch( actual_format_type )
+    {
+     case 8:
+       push_string(make_shared_binary_string((char *)retdata,actual_length));
+       break;
+
+     case 16:
+       push_string(make_shared_binary_string1((p_wchar1 *)retdata,actual_length));
+      break;
+
+     case 32:
+       push_string(make_shared_binary_string2((p_wchar2 *)retdata,actual_length));
+       break;
+    }
+    XFree( retdata );
+    f_aggregate_mapping( 6 );
+    return;
+  }
+  pop_n_elems(args);
+  push_int( 0 );
+}
+
+FUNCTION(change_property, "function(object,object,int,string:object)");
+ARGS(GDK.Atom,GDK.Atom,int,string);
+NAME_ARGS(property,type,mode,data);
+RETURNS(GDK.Window);
+// mode is one of CONST(GDK_PROP_MODE)
+{
+  struct object *o, *t;
+  struct pike_string *s;
+  int m;
+  get_all_args( "delete_property", args, "%o%o%d%W", &o, &t, &m, &s );
+
+  gdk_property_change( (GdkWindow*)THIS->obj, get_gdkatom( o ),
+                       get_gdkatom( t ), 8<<s->size_shift,
+                       m, (unsigned char *)s->str, 
+                       s->len );
+  
+  RETURN_THIS();
+}
+
+FUNCTION(delete_property, "function(object:object)");
+ARGS(GDK.Atom,string);
+NAME_ARGS(property,data);
+RETURNS(GDK.Window);
+{
+  struct object *o;
+  get_all_args( "delete_property", args, "%o", &o );
+  gdk_property_delete( (GdkWindow*)THIS->obj, get_gdkatom( o ) );
+  RETURN_THIS();
+}
+
+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;
+#if PIKE_SECURITY
+  get_all_args("set_background", args, "%O", &o);
+#else
+  get_all_args("set_background", args, "%o", &o);
+#endif
+
+/*   gdk_error_trap_push(); */
+  if(!o)
+    gdk_window_set_back_pixmap( (GdkWindow *)THIS->obj, NULL, 1 );
+  if(get_gdkobject(o,Pixmap))
+    gdk_window_set_back_pixmap((GdkWindow *)THIS->obj,
+                               get_gdkobject(o,Pixmap),0);
+  else if(get_gdkobject(o,Color))
+    gdk_window_set_background((GdkWindow *)THIS->obj, get_gdkobject(o,Color));
+  else
+    error("Set the background to what?\n");
+
+/*   if(gdk_error_trap_pop()) */
+/*     error("Failed to set the background\n"); */
+
+  RETURN_THIS();
+}
diff --git a/src/post_modules/GTK/source/global.pre b/src/post_modules/GTK/source/global.pre
new file mode 100644
index 0000000000000000000000000000000000000000..df2425f96003a914f6aed7ee8bffa5ef3eb64075
--- /dev/null
+++ b/src/post_modules/GTK/source/global.pre
@@ -0,0 +1,234 @@
+/* -*- c -*- */
+
+/*
+GLOBAL_CFUN( button_box_set_child_size_default, int, int );
+GLOBAL_CFUN( button_box_set_child_ipadding_default, int, int );
+GLOBAL_FUN( button_box_get_child_size_default, "function(void:mapping)"); 
+GLOBAL_FUN( button_box_get_child_ipadding_default, "function(void:mapping)");
+*/
+
+/* The main stuff.. */
+void socket_ready_callback(int fd, void *f)
+{
+  g_main_iteration(1);
+}
+
+static void backend_callback()
+{
+  next_timeout = current_time;
+  next_timeout.tv_usec += 20000;
+  if(next_timeout.tv_usec > 1000000)
+  {
+    next_timeout.tv_usec-=1000000;
+    next_timeout.tv_sec+=1;
+  }
+  while(g_main_iteration( 0 ) );
+}
+
+static struct callback *backend_cb;
+FUNCTION(parse_rc, "function(string:void)");
+NAME_ARGS(rc);
+// Takes a string and reads it as a gtkrc file.
+{
+  char *s;
+  get_all_args("parse_rc", args, "%s", &s );
+  gtk_rc_parse_string( s );
+  pop_n_elems(args);
+  push_int( 0 );
+/*   gtk_widget_propagate_default_style(); */
+}
+
+#include <errno.h>
+#include "builtin_functions.h"
+
+struct object *pgtk_root_window;
+FUNCTION(root_window, "function(void:object)");
+RETURNS(GDK.Window);
+// Returns the root window of the current display (as a GDK.Window)
+{
+  pop_n_elems( args );
+  if(pgtk_root_window) 
+  {
+    ref_push_object( pgtk_root_window );
+    return;
+  } 
+  pgtk_root_window = low_clone( pgtk_GdkWindow_program );
+  call_c_initializers( pgtk_root_window );
+  /* ugly...*/
+  ((struct object_wrapper *)pgtk_root_window->storage)->obj=
+    (void *)&gdk_root_parent;
+  
+ add_ref(pgtk_root_window);
+  ref_push_object( pgtk_root_window );
+}
+
+static void do_error( void *dom, int level, char *err, void *data ) 
+{
+  push_text( err );
+  f_backtrace( 0 );
+  f_aggregate( 2 );
+  APPLY_MASTER("describe_backtrace",1);
+  if(sp[-1].type==T_STRING)
+    write_to_stderr(sp[-1].u.string->str, sp[-1].u.string->len);
+  pop_stack();
+}
+
+int pigtk_is_setup = 0;
+
+FUNCTION(setup_gtk, "function(array|void,int|void:array)");
+NAME_ARGS(argv, do_not_parse_rc);
+// Initialize GTK, and all that comes with it.
+// Also parses $HOME/.pgtkrc and $HOME/.gtkrc if they exists.
+// The single argument, if supplied, is the argument array passed to
+// the program. This is used to set default window titles etc.
+// The second argument, if supplied, indicates that pike specific *rc files
+// should <b>not</b> be parsed.
+// <p>
+// The most common usage is GTK.setup_gtk(argv);
+{
+  char **data;
+  int argc;
+#ifndef NSIG
+#define NSIG 32
+#endif
+  int sig;
+#ifdef HAVE_SIGACTION
+  struct sigaction save_sigs[NSIG];
+  for(sig=1;sig<NSIG;sig++)
+  {
+    int ret;
+    do
+    {
+      ret=sigaction(sig,0,save_sigs+sig);
+    }while(ret == -1 && errno==EINTR);
+  }
+#else /* HAVE_SIGACTION */
+
+#if HAVE_SIGNAL
+#ifndef RETSIGTYPE
+#define RETSIGTYPE void
+#endif
+  typedef RETSIGTYPE (*sigtype)(int);
+  sigtype save_sigs[NSIG];
+  for(sig=1;sig<NSIG;sig++)
+    signal(e,save_sigs[e]=signal(e,SIG_IGN));
+
+#endif /* HAVE_SIGNAL */
+#endif /* ! HAVE_SIGACTION */
+
+
+  pigtk_is_setup = 1;
+
+  if(args)
+  {
+    struct array *a;
+    get_all_args("setup_gtk", args, "%a", &a);
+
+    data = malloc(sizeof(char *)*(a->size+1));
+    for(argc=0; argc<a->size; argc++)
+    {
+      if(a->item[argc].type != T_STRING)
+      {
+        free(data);
+        error("Index %d in the array given as argument to setup_gtk "
+              "is not a string.\n", argc);
+      }
+      data[argc] = a->item[argc].u.string->str;
+    }
+  } else {
+    data = malloc(sizeof(char *)*2);
+    data[0] = "Pike GTK";
+    argc=1;
+  }
+  data[argc] = NULL;
+
+  atexit( (void (*)(void))_exit );
+  g_log_set_handler("Gdk",G_LOG_LEVEL_CRITICAL,(void *)do_error, NULL );
+  g_log_set_handler("Gdk",G_LOG_LEVEL_ERROR,   (void *)do_error, NULL );
+  g_log_set_handler("Gdk",G_LOG_LEVEL_WARNING, (void *)do_error, NULL );
+  g_log_set_handler("Gdk",G_LOG_LEVEL_MESSAGE, (void *)do_error, NULL );
+  g_log_set_handler("Glib",G_LOG_LEVEL_CRITICAL,(void *)do_error, NULL );
+  g_log_set_handler("Glib",G_LOG_LEVEL_ERROR,  (void *)do_error, NULL );
+  g_log_set_handler("Glib",G_LOG_LEVEL_WARNING,(void *)do_error, NULL );
+  g_log_set_handler("Glib",G_LOG_LEVEL_MESSAGE,(void *)do_error, NULL );
+  gtk_init( &argc, &data );
+  g_log_set_handler("Gdk",G_LOG_LEVEL_CRITICAL,(void *)do_error, NULL );
+  g_log_set_handler("Gdk",G_LOG_LEVEL_ERROR,   (void *)do_error, NULL );
+  g_log_set_handler("Gdk",G_LOG_LEVEL_WARNING, (void *)do_error, NULL );
+  g_log_set_handler("Gdk",G_LOG_LEVEL_MESSAGE, (void *)do_error, NULL );
+  g_log_set_handler("Glib",G_LOG_LEVEL_CRITICAL,(void *)do_error, NULL );
+  g_log_set_handler("Glib",G_LOG_LEVEL_ERROR,  (void *)do_error, NULL );
+  g_log_set_handler("Glib",G_LOG_LEVEL_WARNING,(void *)do_error, NULL );
+  g_log_set_handler("Glib",G_LOG_LEVEL_MESSAGE,(void *)do_error, NULL );
+  g_log_set_handler("Gtk",G_LOG_LEVEL_CRITICAL,(void *)do_error, NULL );
+  g_log_set_handler("Gtk",G_LOG_LEVEL_ERROR,   (void *)do_error, NULL );
+  g_log_set_handler("Gtk",G_LOG_LEVEL_WARNING, (void *)do_error, NULL );
+  g_log_set_handler("Gtk",G_LOG_LEVEL_MESSAGE, (void *)do_error, NULL );
+  atexit( (void (*)(void))_exit );
+
+#ifdef HAVE_SIGACTION
+  for(sig=1;sig<NSIG;sig++)
+  {
+    int ret;
+    do ret=sigaction(sig,save_sigs+sig,0); while(ret == -1 && errno==EINTR);
+  }
+#else /* HAVE_SIGACTION */
+#if HAVE_SIGNAL
+  for(sig=1;sig<NSIG;sig++)
+    signal(e,save_sigs[e]);
+#endif /* HAVE_SIGNAL */
+#endif /* HAVE_SIGACTION */
+  backend_cb = (void *)add_backend_callback( backend_callback, 0, 0);
+  /* Get the display fd.. */
+#ifndef __NT__
+  {
+    Display *d = GDK_DISPLAY();
+    int fd;
+    if(!d) {
+      error("Failed to get GDK display.\n");
+      free(data);
+    }
+    fd = ConnectionNumber( d );
+    set_read_callback( fd, socket_ready_callback, NULL );
+  }
+#else
+# error Fixme. This needs some work.
+#endif  
+
+  pop_n_elems(args);
+  /*
+   * Now it's time to return the leftovers.
+   */
+  for( sig=0; sig<argc; sig++ )
+    push_text( data[sig] );
+  f_aggregate( argc );
+  free(data);
+}
+
+FUNCTION(flush, "function(void:void)")
+// Flush GDK. Not normally needed, can be useful while doing calculations.
+{
+  gdk_flush();
+  while(g_main_iteration( 0 ) );
+  pop_n_elems(args);
+  push_int(0);
+}
+
+FUNCTION(low_flush, "function(void:void)")
+// Flush X. Not normally needed.
+{
+  XFlush( GDK_DISPLAY() );
+  pop_n_elems( args );
+  push_int( 0 );
+}
+
+FUNCTION(gtk_init, "function(array|void,int|void:array)");
+NAME_ARGS(argc,no_pgtkrc);
+// Low level GTK init function (used by setup_gtk).
+// This function is more or less equivalent to the C-GTK+ function gtk_init
+// setup_gtk does some extra things (such as parsing ~/.pgtkrc).
+{
+  pgtk_global_setup_gtk( args );
+}
+
+
diff --git a/src/post_modules/GTK/source/gtkaccelgroup.pre b/src/post_modules/GTK/source/gtkaccelgroup.pre
new file mode 100644
index 0000000000000000000000000000000000000000..b2acf4f9061834730fb05aa9ce56d9875a36583d
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkaccelgroup.pre
@@ -0,0 +1,74 @@
+PROGRAM(accel_group);
+INHERIT(data);
+// An AccelGroup stores keybindings.
+// A group is automatically created by W(MenuFactory)
+//
+// NOIMG
+FUNCTION(create, "function(void:void)")
+ARGS();
+// Create a new object
+{
+  THIS->obj = (void *)gtk_accel_group_new();
+ add_ref(fp->current_object); /* one extra ref... */
+}
+FUNCTION(add_accel, "function(object,string,int,int:object)");
+RETURNS(GTK.AccelGroup);
+ARGS(GTK.Widget,string,int,int,int);
+NAME_ARGS(widget,signal,key,modifiers,flags);
+// the widget is the one in which the signal specified by 'signal'
+// recides.
+// The key is the character code (such as 'a' for the a key and '@' for the @
+// key), and modifiers is a bitmap of one or more bits, the bits are
+// CONST(_MASK). Flags is one or more of CONST(GTK_ACCEL)
+{
+  struct object *o;
+  int k;
+  char *sig;
+  int mods;
+  int flags;
+  get_all_args("add_accel", args, "%o%s%d%d", &o, &sig, &k, &mods, &flags );
+  gtk_accel_group_add((void *)THIS->obj, k, mods, flags, 
+                      get_gtkobject( o ), sig );
+  RETURN_THIS();
+}
+
+FUNCTION(remove, "function(object,string:object)");
+ARGS(GTK.Widget,string);
+NAME_ARGS(object,key,modifiers);
+RETURNS(GTK.AccelGroup);
+// Remove all bindings for the specified key/mask in the specified object.
+{
+  struct object *o;
+  int k, mods;
+  get_all_args("remove", args, "%o%d%d", &o, &k, &mods );
+  gtk_accel_group_remove((void *)THIS->obj, k,mods, get_gtkobject( o ));
+  RETURN_THIS();
+}
+/* FUNCTION(check, "function(int,int:int)"); */
+/* NAME_ARGS(key,modifiers); */
+/* // Returns true if there is a shortcut for the specified key and modifiers. */
+/* { */
+/*   int k, mod; */
+/*   get_all_args("check", args, "%d%d", &k, &mod ); */
+/*   pop_n_elems(args); */
+/*   push_int( gtk_accelerator_table_check( (void *)THIS->obj, k, mod ) ); */
+/* } */
+/* FUNCTION(set_mod_mask, "function(int:object)") */
+/* NAME_ARGS(mask); */
+/* RETURNS(GTK.AcceleratorTable); */
+/* // sets the default modifier mask. All modifiers are masked with this mask */
+/* // before the shortcut specific masks are tested. */
+/* { */
+/*   int mod; */
+/*   get_all_args("set_mask", args, "%d", &mod ); */
+/*   gtk_accelerator_set_default*-,pd_maskerator_table_set_mod_mask( (void *)THIS->obj, mod ); */
+/*   RETURN_THIS(); */
+/* } */
+
+FUNCTION(destroy, "function(void:void)")
+{
+  gtk_accel_group_unref( (void *)THIS->obj );
+  THIS->obj = 0;
+}
+
+/* TODO: Some functions left... */
diff --git a/src/post_modules/GTK/source/gtkaccellabel.pre b/src/post_modules/GTK/source/gtkaccellabel.pre
new file mode 100644
index 0000000000000000000000000000000000000000..6776921f1a9d3c5041b09580d9544818c6036291
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkaccellabel.pre
@@ -0,0 +1,9 @@
+PROGRAM(accel_label);
+INHERIT(label);
+// A label for accelerators.
+COMPLEX_FUNCTION(create,string);
+NAME_ARGS(text);
+int COMPLEX_FUNCTION(get_accel_width);
+COMPLEX_FUNCTION(set_accel_widget, widget);
+NAME_ARGS(accel_widget);
+int COMPLEX_FUNCTION(refetch);
diff --git a/src/post_modules/GTK/source/gtkadjustment.pre b/src/post_modules/GTK/source/gtkadjustment.pre
new file mode 100644
index 0000000000000000000000000000000000000000..506058ce005ab0198700603936966f1760379379
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkadjustment.pre
@@ -0,0 +1,87 @@
+PROGRAM(adjustment);
+// The GtkAdjustment object represents a value which has an associated
+// lower and upper bound, together with step and page increments, and
+// a page size. It is used within several GTK+ widgets, including
+// GtkSpinButton, GtkViewport, and GtkRange (which is a base class for
+// GtkHScrollbar, GtkVScrollbar, GtkHScale, and GtkVScale).
+// <p>
+// The GtkAdjustment object does not update the value itself. Instead
+// it is left up to the owner of the GtkAdjustment to control the
+// value.
+// <p>
+// The owner of the GtkAdjustment typically calls the value_changed()
+// and changed() functions after changing the value or its
+// bounds. This results in the emission of the "value_changed" or
+// "changed" signal respectively.
+// <p>
+/*
+  // Example:
+  // IMG: lambda() {object a;object h = GTK.Hbox(0,0);h->add(GTK.Text(GTK.Adjustment(),(a=GTK.Adjustment())))->add(GTK.Vscrollbar( a ));return h;}()
+*/
+SIGNAL("changed", "The adjustment changed in some way");
+SIGNAL("value_changed", "The value changed.");
+INHERIT(data);
+FUNCTION(create, "function(void|float,void|float,void|float,void|float,void|float,void|float:void)")
+NAME_ARGS(value,lower,upper,step_increment,page_increment,page_size);
+// Normal operaion: w(Adjustment);
+// using no arguments gives defaults of 0.0 1.0 0.0 0.01 0.01 1.0.
+// If you want to specify all values, they are:
+// value, lower, upper, step_increment, page_increment and page_size
+// All are floating point values. For most widgets the unit is pixels.
+{
+  float l=0.0, u=1.0, v=0.0, si=0.01, pi=0.01, ps=1.0;
+  if(args == 6 )
+    get_all_args("Adjustment", args,"%f%f%f%f%f%f", &l,&u,&v,&si,&pi,&ps);
+  else if(args == 3 )   get_all_args("Adjustment", args,"%f%f%f", &l,&u,&v);
+  else if(args == 2 )   get_all_args("Adjustment", args,"%f%f", &l,&u);
+
+  if(THIS->obj) error("GTK.Adjustment->create() can only be called once.\n");
+  THIS->obj = GTK_OBJECT( gtk_adjustment_new( l, u, v, si, pi, ps ) );
+  if(!THIS->obj) 
+    error("Failed to initiate adjustment\n");
+  pgtk__init_this_object();
+  pop_n_elems(args);
+  push_int( 0 );
+}
+COMPLEX_FUNCTION(set_value, float);
+NAME_ARGS(to);
+// Set the value component.
+CLASSMEMBER(value,float);
+// Get the value component.
+CLASSMEMBER(lower, float);
+// Get the lower limit.
+CLASSMEMBER(upper, float);
+// Get the upper limit.
+CLASSMEMBER(step_increment, float);
+// Get the step increment (arrow click)
+CLASSMEMBER(page_increment, float);
+// Get the page increment (page down or through click)
+CLASSMEMBER(page_size, float);
+// Get the page size (the actual size of a page)
+SETCLASSMEMBER(lower, float);
+NAME_ARGS(new_lower);
+// Set the lower limit.
+// <br>Returns the old value.
+SETCLASSMEMBER(upper, float);
+NAME_ARGS(new_upper);
+// Set the upper limit.
+// <br>Returns the old value.
+SETCLASSMEMBER(step_increment, float);
+NAME_ARGS(new_increment);
+// Set the step increment (arrow click)
+// <br>Returns the old value.
+SETCLASSMEMBER(page_increment, float);
+NAME_ARGS(new_increment);
+// Set the page increment (page down or through click)
+// <br>Returns the old value.
+SETCLASSMEMBER(page_size, float);
+NAME_ARGS(new_size);
+// Set the page size (the actual size of a page)
+// <br>Returns the old value.
+COMPLEX_FUNCTION(clamp_page, float, float);
+NAME_ARGS(lower, upper);
+// Updates the GtkAdjustment value to ensure that the range between
+// lower and upper is in the current page (i.e. between value and
+// value + page_size). If the range is larger than the page size, then
+// only the start of it will be in the current page. A "changed"
+// signal will be emitted if the value is changed.
diff --git a/src/post_modules/GTK/source/gtkalignment.pre b/src/post_modules/GTK/source/gtkalignment.pre
new file mode 100644
index 0000000000000000000000000000000000000000..8a47aa8e0f8d8f50c0cb2db28d3a977a05ac63f8
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkalignment.pre
@@ -0,0 +1,59 @@
+PROGRAM(alignment);
+// The W(Alignment) widget controls the alignment and size of its
+// child widget. It has four settings: xscale, yscale, xalign, and
+// yalign.
+// <p>
+// The scale settings are used to specify how much the child widget
+// should expand to fill the space allocated to the W(Alignment). The
+// values can range from 0 (meaning the child doesn't expand at all)
+// to 1 (meaning the child expands to fill all of the available
+// space).
+// <p>
+// The align settings are used to place the child widget within the
+// available area. The values range from 0 (top or left) to 1 (bottom
+// or right). Of course, if the scale settings are both set to 1, the
+// alignment settings have no effect.
+//
+// NOIMG
+INHERIT(bin);
+
+COMPLEX_FUNCTION(create, float, float, float, float);
+NAME_ARGS(xalign,yalign,xscale,yscale);
+// <table>
+// <tr><td>xalign :</td>
+// <td>the horizontal alignment of the child widget, from 0 (left) to 1 (right).</td></tr>
+// <tr><td>                  yalign :</td>
+// <td>the vertical alignment of the child widget, from 0 (top) to 1 (bottom).</td></tr>
+// <tr><td>                  xscale :</td>
+// <td>the amount that the child widget expands horizontally to fill up unused space, from 0 to 1. A value of 0 indicates that the child widget should never expand. A value of 1 indicates that the child widget will expand to fill all of the space allocated for the GTK.Alignment.</td></tr>
+// <tr><td>                  yscale :</td>
+// <td>the amount that the child widget expands vertically to fill up unused space, from 0 to 1. The values are similar to xscale.</td></tr>
+// </table>
+
+
+COMPLEX_FUNCTION(set, float, float, float, float);
+NAME_ARGS(xalign,yalign,xscale,yscale);
+// <table>
+// <tr><td>xalign :</td>
+// <td>the horizontal alignment of the child widget, from 0 (left) to 1 (right).</td></tr>
+// <tr><td>                  yalign :</td>
+// <td>the vertical alignment of the child widget, from 0 (top) to 1 (bottom).</td></tr>
+// <tr><td>                  xscale :</td>
+// <td>the amount that the child widget expands horizontally to fill up unused space, from 0 to 1. A value of 0 indicates that the child widget should never expand. A value of 1 indicates that the child widget will expand to fill all of the space allocated for the GTK.Alignment.</td></tr>
+// <tr><td>                  yscale :</td>
+// <td>the amount that the child widget expands vertically to fill up unused space, from 0 to 1. The values are similar to xscale.</td></tr>
+// </table>
+
+CLASSMEMBER(xalign, float);
+// the horizontal alignment of the child widget, from 0 (left) to 1 (right).
+CLASSMEMBER(yalign, float);
+// the vertical alignment of the child widget, from 0 (top) to 1 (bottom).
+CLASSMEMBER(xscale, float);
+// the amount that the child widget expands horizontally to fill up
+// unused space, from 0 to 1. A value of 0 indicates that the child
+// widget should never expand. A value of 1 indicates that the child
+// widget will expand to fill all of the space allocated for the
+// GTK.Alignment.
+CLASSMEMBER(yscale, float);
+// the amount that the child widget expands vertically to fill up
+// unused space, from 0 to 1. The values are similar to xscale.
diff --git a/src/post_modules/GTK/source/gtkarrow.pre b/src/post_modules/GTK/source/gtkarrow.pre
new file mode 100644
index 0000000000000000000000000000000000000000..7b2f335bffdb82567bb87c1aee01baa0be5bf4ec
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkarrow.pre
@@ -0,0 +1,19 @@
+PROGRAM(arrow);
+INHERIT(misc);
+// An arrow pointing in one of four directions. The 'etched' shadow
+// types does not work.
+
+// IMG: GTK.Arrow(GTK.ARROW_UP, GTK.SHADOW_OUT)
+// IMG: GTK.Arrow(GTK.ARROW_LEFT, GTK.SHADOW_IN)
+// IMG: GTK.Arrow(GTK.ARROW_RIGHT, GTK.SHADOW_IN)
+// IMG: GTK.Arrow(GTK.ARROW_DOWN, GTK.SHADOW_OUT)
+COMPLEX_FUNCTION(create, int, int);
+NAME_ARGS(arrow_type,shadow_type);
+// First argument is one of CONST(GTK_ARROW), second one of CONST(GTK_SHADOW).
+COMPLEX_FUNCTION(set, int, int);
+NAME_ARGS(arrow_type,shadow_type);
+// First argument is one of CONST(GTK_ARROW), second one of CONST(GTK_SHADOW).
+CLASSMEMBER(arrow_type, int);
+// Return the arrow type. One of CONST(GTK_ARROW).
+CLASSMEMBER(shadow_type, int);
+// Return the arrow type. One of CONST(GTK_SHADOW).
diff --git a/src/post_modules/GTK/source/gtkaspectframe.pre b/src/post_modules/GTK/source/gtkaspectframe.pre
new file mode 100644
index 0000000000000000000000000000000000000000..9a797293afeacf0f02e2c894fba59d5617663c3b
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkaspectframe.pre
@@ -0,0 +1,21 @@
+/* -*- c -*- */
+PROGRAM(aspect_frame);
+// A W(Frame) widget  that always maintain a specified ratio
+// between width and height. width/height == ratio
+//
+// IMG: GTK.Aspect_frame("Title",0.5,0.5,0.4,0)->add( GTK.Label("Wrong aspect"))->set_usize(200,200)
+
+INHERIT(frame);
+COMPLEX_FUNCTION(set, float,float,float,int);
+NAME_ARGS(xalign,yalign,ratio,obey_child);
+// Set the aspec values. Arguments are xalign, yalign, ratio, obey_child
+// xalign is floats between 0 and 1, 0.0 is upper (or leftmost), 1.0 is
+// lower (or rightmost). If 'obey_child' is true, the frame will use the
+// aspect ratio of it's (one and only) child widget instead of 'ratio'.
+
+COMPLEX_FUNCTION(create,string,float,float,float,int);
+NAME_ARGS(label,xalign,yalign,ratio,obey_child);
+// Create a new frame. Arguments are label, xalign, yalign, ratio, obey_child
+// xalign is floats between 0 and 1, 0.0 is upper (or leftmost), 1.0 is
+// lower (or rightmost). If 'obey_child' is true, the frame will use the
+// aspect ratio of it's (one and only) child widget instead of 'ratio'.
diff --git a/src/post_modules/GTK/source/gtkbin.pre b/src/post_modules/GTK/source/gtkbin.pre
new file mode 100644
index 0000000000000000000000000000000000000000..1ec89d3a4d9f02fb291c9e2b34b0e6d51605b7cc
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkbin.pre
@@ -0,0 +1,5 @@
+PROGRAM(bin);
+// A container that can only contain one child.
+INHERIT(container);
+SUBWIDGET(child, widget);
+// Returns the (one and only) child of this container.
diff --git a/src/post_modules/GTK/source/gtkbox.pre b/src/post_modules/GTK/source/gtkbox.pre
new file mode 100644
index 0000000000000000000000000000000000000000..5337e0a5e22c2ef7de2520fe00821c136d703bc2
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkbox.pre
@@ -0,0 +1,70 @@
+/* -*- c -*- */
+
+PROGRAM(box);
+// A box is a container that can contain more than one child.
+// The basic 'Box' class cannot be instantiated, it is a virtual class
+// that only defines some common 'Box' functions shared with all other
+// Box widgets.
+INHERIT(container);
+COMPLEX_FUNCTION(pack_start, WIDGET,int,int,int);
+NAME_ARGS(widget, expandp, fillp, padding);
+// Pack from the left (or top) of the box. 
+// Argument are widget, expand, fill, padding
+// pack(widget,1,1,0) is equivalent to 'add' or 'pack_start_defaults'
+COMPLEX_FUNCTION(pack_end, WIDGET,int,int,int);
+NAME_ARGS(widget, expandp, fillp, padding);
+// Pack from the right (or bottom) of the box. 
+// Arguments are widget, expand, fill, paddingb
+// widget, expand, fill, padding
+SIMPLE_WIDGET_FUNCTION(pack_start_defaults);
+NAME_ARGS(widget);
+// The argument is the widget to add. This function is equivalent to 'add'
+SIMPLE_WIDGET_FUNCTION(pack_end_defaults);
+NAME_ARGS(widget);
+// The argument is the widget to add.
+SIMPLE_INT_FUNCTION(set_homogeneous);
+NAME_ARGS(homogeneousp);
+// If true, all widgets in the box will get exactly the same amount of space
+SIMPLE_INT_FUNCTION(set_spacing);
+NAME_ARGS(spacing);
+// This is the amount of spacing (in pixels) inserted beween all widgets
+COMPLEX_FUNCTION(reorder_child, widget, int);
+NAME_ARGS(child_widget,new_position);
+// Move widget to pos, pos is an integer, 
+// between 0 and sizeof(box->children())-1
+COMPLEX_FUNCTION(set_child_packing, WIDGET,int,int,int,int);
+NAME_ARGS(child_widget,expandp,fillp,padding,pack_type);
+// widget, expand, fill, padding, pack_type. 
+// If exand is true, the widget will be expanded when the box is resized.
+// If 'fill' is true, the widget will be resized to fill up all available
+// space. Padding is the amount of padding to use, and pack_type is
+// one of CONST(GTK_PACK).
+// <p>
+// You can emulate pack_start and pack_end with add and set_child_packing.
+FUNCTION(query_child_packing, "function(object:mapping)");
+ARGS(GTK.Widget);
+NAME_ARGS(child);
+RETURNS("mapping(string:int)");
+// Return a mapping:<br>
+// ([ "expand":expandp, "fill":fillp, "padding":paddingp, "type":type ])
+{
+  struct object *o;
+  gint  pa;
+  gboolean ex, fi;
+  GtkPackType ty;
+  get_all_args( "query_child_packing", args, "%o", &o);
+  gtk_box_query_child_packing( GTK_BOX( THIS->obj ), 
+                               GTK_WIDGET( get_gtkobject( o ) ),
+                               &ex, &fi, &pa, &ty );
+  pop_n_elems( args );
+  push_constant_text( "expand" );
+  push_int( ex );
+  push_constant_text( "fill" );
+  push_int( fi );
+  push_constant_text( "padding" );
+  push_int( pa );
+  push_constant_text( "type" );
+  push_int( ty );
+  f_aggregate_mapping( 6 );
+}
+
diff --git a/src/post_modules/GTK/source/gtkbutton.pre b/src/post_modules/GTK/source/gtkbutton.pre
new file mode 100644
index 0000000000000000000000000000000000000000..bcb0d2ac7f9d73e9df779a5d19a5181c797ffd67
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkbutton.pre
@@ -0,0 +1,46 @@
+PROGRAM(button);
+// A container that can only contain one child, and accepts events.
+// draws a bevelbox around itself.
+// IMG: GTK.Button("A button")
+// IMG: GTK.Button("A button\nwith multiple lines\nof text")
+// IMG: GTK.Button()->add(GTK.Image(GDK.Image(0)->set(Image.image(100,40)->test())))
+INHERIT(container);
+SUBWIDGET(child, widget);
+// Returns the (one and only) child of this container.
+
+SIGNAL("pressed", "Called when the button is pressed");
+SIGNAL("released", "Called when the button is released");
+SIGNAL("clicked", "Called when the button is pressed, and then released");
+SIGNAL("enter", "Called when the mouse enters the button");
+SIGNAL("leave", "Called when the mouse leaves the button");
+
+FUNCTION(create, "function(string|void:void)")
+NAME_ARGS(label_text);
+// If a string is supplied, a W(Label) is created and added to the button.
+{
+  if(THIS->obj) error("GTK.Button->create() can only be called once.\n");
+  if(args)
+  {
+    char *s;
+    get_all_args("GTK.Button", args, "%s", &s);
+    THIS->obj = GTK_OBJECT( gtk_button_new_with_label( s ) );
+  } else {
+    THIS->obj = GTK_OBJECT( gtk_button_new( ) );
+  }
+  pgtk__init_this_object();
+}
+SIMPLE_FUNCTION(pressed);
+// Emulate a 'press' event.
+SIMPLE_FUNCTION(released);
+// Emulate a 'release' event.
+SIMPLE_FUNCTION(clicked);
+// Emulate a 'clicked' event (press followed by release). 
+SIMPLE_FUNCTION(enter);
+// Emulate a 'enter' event.
+SIMPLE_FUNCTION(leave);
+// Emulate a 'leave' event.
+SIMPLE_INT_FUNCTION(set_relief);
+NAME_ARGS(newstyle);
+// One of CONST(GTK_RELIEF)
+int COMPLEX_FUNCTION(get_relief);
+// One of CONST(GTK_RELIEF), set with set_relief()
diff --git a/src/post_modules/GTK/source/gtkbuttonbox.pre b/src/post_modules/GTK/source/gtkbuttonbox.pre
new file mode 100644
index 0000000000000000000000000000000000000000..0bb77fd258cac26cc92387696b59230dd54ad436
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkbuttonbox.pre
@@ -0,0 +1,49 @@
+/* -*- c -*- */
+PROGRAM(button_box);
+// More or less equivalent to a normal box, but you can set a few
+// layout schemes that are not available for normal boxes.
+// See the hbox and vbox documentation for examples.
+INHERIT(box);
+SIMPLE_INT_FUNCTION(set_spacing);
+NAME_ARGS(spacing);
+// in pixels
+SIMPLE_INT_FUNCTION(set_layout);
+NAME_ARGS(layout);
+// layout is one of CONST(GTK_BUTTONBOX)
+COMPLEX_FUNCTION(set_child_size, int, int);
+NAME_ARGS(child_number, child_size);
+// Set the size of a specified child
+
+COMPLEX_FUNCTION(set_child_ipadding, int, int);
+NAME_ARGS(child_number, child_padding);
+// Set the padding for a specific child.
+
+int COMPLEX_FUNCTION(get_spacing);
+// Return the spacing that is added between the buttons
+int COMPLEX_FUNCTION(get_layout);
+// Returns the currently configured layout.
+// One of  CONST(GTK_BUTTONBOX)
+FUNCTION(get_child_size, "function(void:mapping)");
+// Return the child size as ([ "x":xsize, "y":ysize ]) 
+{
+  int x, y;
+  pop_n_elems(args);
+  gtk_button_box_get_child_size( GTK_BUTTON_BOX( THIS->obj ), &x, &y );
+  push_constant_text( "x" );
+  push_int( x );
+  push_constant_text( "y" );
+  push_int( y );
+  f_aggregate_mapping( 4 );
+}
+FUNCTION(get_child_ipadding, "function(void:mapping)");
+// Return the default inter-child padding ([ "x":xpadding, "y":ypadding ]) 
+{
+  int x, y;
+  pop_n_elems(args);
+  gtk_button_box_get_child_ipadding( GTK_BUTTON_BOX( THIS->obj ), &x, &y );
+  push_constant_text( "x" );
+  push_int( x );
+  push_constant_text( "y" );
+  push_int( y );
+  f_aggregate_mapping( 4 );
+}
diff --git a/src/post_modules/GTK/source/gtkcalendar.pre b/src/post_modules/GTK/source/gtkcalendar.pre
new file mode 100644
index 0000000000000000000000000000000000000000..1aac8b1e6ec01330186e464e8e4eb8d5f28de703
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkcalendar.pre
@@ -0,0 +1,130 @@
+PROGRAM(calendar);
+// A calendar widget.
+// IMG: GTK.Calendar();
+// IMG: GTK.Calendar()->select_day( 16 );
+INHERIT(widget);
+
+SIGNAL("month_changed", "");
+SIGNAL("day_selected", "");
+SIGNAL("day_selected_double_click", "");
+SIGNAL("prev_month", "");
+SIGNAL("next_month", "");
+SIGNAL("prev_year", "");
+SIGNAL("next_year", "");
+
+COMPLEX_FUNCTION(create);
+// Create a new calendar widget
+
+int COMPLEX_FUNCTION(select_month, int, int);
+NAME_ARGS(month, year);
+// Select the month to be viewed.
+
+COMPLEX_FUNCTION(select_day, int);
+NAME_ARGS(day_of_month);
+// Select a certain day of the currently selected month
+
+COMPLEX_FUNCTION(mark_day, int);
+NAME_ARGS(day_of_month);
+// Mark a day
+
+COMPLEX_FUNCTION(unmark_day, int);
+NAME_ARGS(day_of_month);
+// Unmark a day
+
+SIMPLE_FUNCTION(clear_marks);
+// Remove all day markers
+COMPLEX_FUNCTION(display_options, int);
+NAME_ARGS(options);
+// Bitwise or of one or more of CONST(GTK_CALENDAR).
+
+FUNCTION(get_date, "function(void:mapping)");
+// returns a mapping:<br>
+// ([ "year":year, "month":month, "day":day ])
+{
+  guint y, m, d;
+  gtk_calendar_get_date( GTK_CALENDAR( THIS->obj ), &y, &m, &d );
+  push_text("year");
+  push_int( y );
+  push_text("month");
+  push_int( m );
+  push_text("day");
+  push_int( d );
+}
+
+SIMPLE_FUNCTION(freeze);
+// Suspend all dynamic updating of the widget
+SIMPLE_FUNCTION(thaw);
+// Resume dynamic updating of the widget
+
+CLASSMEMBER(focus_row, int);
+// The currently focused row
+CLASSMEMBER(focus_col, int);
+// The currently focused column
+CLASSMEMBER(highlight_row, int);
+// The currently highlighted row
+CLASSMEMBER(highlight_col, int);
+// The currently highlighted column
+
+CLASSMEMBER(month, int);
+// The current month
+CLASSMEMBER(year, int);
+// The current year
+CLASSMEMBER(selected_day, int);
+// The currently selected day
+CLASSMEMBER(num_marked_dates, int);
+// The number of days that are marked
+
+FUNCTION(get_marked_dates, "function(void:array(int))");
+// Returns an array (with 31 elements) with 1es and 0es.
+{
+  int i;
+  for(i=0; i<31; i++)
+    push_int( GTK_CALENDAR( THIS->obj )->marked_date[i] );
+  f_aggregate( 31 );
+}
+
+FUNCTION(get_day_month, "function(void:array(array(int)))");
+// Return an array of 6x7 days, representing the cells in the 
+// currently viewed calendar month.  The value is the day of month.
+{
+  int i,j;
+  for(i=0; i<6; i++)
+  {
+    for(j=0; j<7; i++)
+      push_int( GTK_CALENDAR( THIS->obj )->day_month[i][j] );
+    f_aggregate( 7 );
+  }
+  f_aggregate( 6 );
+}
+
+FUNCTION(get_day, "function(void:array(array(int)))");
+// Return an array of 6x7 days, representing the cells in the 
+// currently viewed calendar month. 
+{
+  int i,j;
+  for(i=0; i<6; i++)
+  {
+    for(j=0; j<7; i++)
+      push_int( GTK_CALENDAR( THIS->obj )->day[i][j] );
+    f_aggregate( 7 );
+  }
+  f_aggregate( 6 );
+}
+
+FUNCTION(set_marked_date_color, "function(int,object:object)");
+ARGS(int,GDK.Color);
+NAME_ARGS(index,color);
+// Set the color to use to mark dates
+{
+  int n;
+  struct object *o;
+  get_all_args( "set_marked_date_color", args, "%d%o", &n, &o );
+  if(!get_gdkobject(o, Color))
+    error("Argument 2 is not a GDK.Color object\n");
+  n--;
+  if(n > 30 || n<0)
+    error("Argument 1 is not between 1 and 31, inclusive\n");
+  GTK_CALENDAR( THIS->obj )->marked_date_color[n] = *get_gdkobject(o, Color);
+  RETURN_THIS();
+}
+
diff --git a/src/post_modules/GTK/source/gtkcheckbutton.pre b/src/post_modules/GTK/source/gtkcheckbutton.pre
new file mode 100644
index 0000000000000000000000000000000000000000..d2fd1a1ece7c1aaca12a0069b2be3f104546060e
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkcheckbutton.pre
@@ -0,0 +1,26 @@
+PROGRAM(check_button);
+// Check buttons inherent many properties and functions from the the
+// toggle buttons, but look a little different. Rather than
+// being buttons with text inside them, they are small squares with
+// the text to the right of them. These are often used for toggling
+// options on and off in applications.
+// IMG: GTK.Check_button( "title" )
+INHERIT(toggle_button);
+FUNCTION(create, "function(string|void:void)")
+NAME_ARGS(label);
+// The argument, if specified, is the label of the item.
+// If no label is specified, use object->add() to add some
+// other widget (such as an pixmap or image widget)
+{
+  if(THIS->obj) error("GTK.Check_button->create() can only be called once.\n");
+  if(args)
+  {
+    char *s;
+    get_all_args("GTK.Check_button", args, "%s", &s);
+    THIS->obj = GTK_OBJECT( gtk_check_button_new_with_label( s ) );
+  } else {
+    THIS->obj = GTK_OBJECT( gtk_check_button_new( ) );
+  }
+  pgtk__init_this_object();
+}
+
diff --git a/src/post_modules/GTK/source/gtkcheckmenuitem.pre b/src/post_modules/GTK/source/gtkcheckmenuitem.pre
new file mode 100644
index 0000000000000000000000000000000000000000..e9de6f23f7d0e85d836e00a3752823049119e18a
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkcheckmenuitem.pre
@@ -0,0 +1,32 @@
+PROGRAM(check_menu_item);
+// A check menu item is more or less identical to a check button, but it
+// should be used in menus.
+// IMG: GTK.CheckMenuItem("Hi there")
+// IMG: GTK.CheckMenuItem("Hi there")->set_active(1)
+SIGNAL("toggled", "Called when the state of the menu item is changed");
+INHERIT(menu_item);
+FUNCTION(create, "function(string|void:void)")
+NAME_ARGS(label);
+// The argument, if specified, is the label of the item.
+// If no label is specified, use object->add() to add some
+// other widget (such as an pixmap or image widget)
+{
+  if(THIS->obj) error("GTK.Check_menu_item->create() can only be called once.\n");
+  if(args)
+  {
+    char *s;
+    get_all_args("GTK.Check_menu_item", args, "%s", &s);
+    THIS->obj = GTK_OBJECT( gtk_check_menu_item_new_with_label( s ) );
+  } else {
+    THIS->obj = GTK_OBJECT( gtk_check_menu_item_new( ) );
+  }
+  pgtk__init_this_object();
+}
+SIMPLE_INT_FUNCTION(set_active);
+NAME_ARGS(new_state);
+// State is either 1 or 0. If 1, the button will be 'pressed'.
+SIMPLE_INT_FUNCTION(set_show_toggle);
+// If true, the toggle indicator will be shown
+NAME_ARGS(togglep);
+SIMPLE_FUNCTION(toggled);
+// Emulate a toggled event
diff --git a/src/post_modules/GTK/source/gtkclist.pre b/src/post_modules/GTK/source/gtkclist.pre
new file mode 100644
index 0000000000000000000000000000000000000000..25e0b2460e905daae1131ccf85c51b0a7f60aebf
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkclist.pre
@@ -0,0 +1,719 @@
+PROGRAM(clist);
+
+// The GtkCList widget is a multi-column list widget that is capable
+// of handling literally thousands of rows of information. Each column
+// can optionally have a title, which itself is optionally active,
+// allowing us to bind a function to it's selection.
+
+// IMG: GTK.Clist(2)->set_column_title(0,"Col 1")->set_column_title(1,"Col 2")->column_titles_show()->set_column_width(0,50)->set_usize(150,70)
+
+SIGNAL("select_row", "Called when a row is selected");
+SIGNAL("unselect_row", "Called when a row is deselected");
+SIGNAL("click_column", "Called when a column is clicked");
+SIGNAL("resize_column", "Called when a column is resized");
+SIGNAL("toggle_focus_row", "");
+SIGNAL("select_all",       "");
+SIGNAL("unselect_all",     "");
+SIGNAL("undo_selection",   "");
+SIGNAL("start_selection",  "");
+SIGNAL("end_selection",    "");
+SIGNAL("toggle_add_mode",  "");
+SIGNAL("extend_selection", "");
+SIGNAL("scroll_vertical",  "");
+SIGNAL("scroll_horizontal",   "");
+SIGNAL("abort_column_resize", "");
+
+
+INHERIT(container);
+/* FIXME: add with titles later on.. */
+COMPLEX_FUNCTION(create, int);
+NAME_ARGS(columns);
+// Create a new empty clist, columns columns wide.  
+// <p> 
+// Not all
+// columns have to be visible, some can be used to store data that is
+// related to a certain cell in the list.
+
+COMPLEX_FUNCTION(set_hadjustment, adjustment);
+NAME_ARGS(adjustment);
+// Set the W(Adjustment) object used for horizontal scrolling
+COMPLEX_FUNCTION(set_vadjustment, adjustment);
+NAME_ARGS(adjustment);
+// Set the W(Adjustment) object used for vertical scrolling
+
+adjustment COMPLEX_FUNCTION(get_hadjustment);
+// Return the W(Adjustment) object used for horizontal scrolling
+adjustment COMPLEX_FUNCTION(get_vadjustment);
+// Return the W(Adjustment) object used for vertical scrolling
+
+
+SIMPLE_INT_FUNCTION(set_shadow_type);
+NAME_ARGS(shadowtype);
+// One of CONST(GTK_SHADOW)
+
+SIMPLE_INT_FUNCTION(set_selection_mode);
+NAME_ARGS(mode);
+// One of CONST(GTK_SELECTION)<br>
+
+COMPLEX_FUNCTION(set_reorderable, int);
+NAME_ARGS(reorderablep);
+// If true, the user can drag around the rows in the list.
+COMPLEX_FUNCTION(set_use_drag_icons, int);
+NAME_ARGS(dragiconsp);
+// If true, hard coded drag icons will be used.
+COMPLEX_FUNCTION(set_button_actions, int, int);
+NAME_ARGS(button,action);
+// Action is a bitwise or of CONST(GTK_BUTTON)<br>
+// Button is the mouse button (normally 1-3, 4 and 5 sometimes beeing
+// scroll wheel up and scroll wheel down)
+
+SIMPLE_FUNCTION(freeze);
+// freeze all visual updates of the list, and then thaw the list after
+// you have made a number of changes and the updates wil occure in a
+// more efficent mannor than if you made them on a unfrozen list
+SIMPLE_FUNCTION(thaw);
+// freeze all visual updates of the list, and then thaw the list after
+// you have made a number of changes and the updates wil occure in a
+// more efficent mannor than if you made them on a unfrozen list
+
+SIMPLE_FUNCTION(column_titles_show);
+// Show the column titles.
+SIMPLE_FUNCTION(column_titles_hide);
+// Hide the column titles
+SIMPLE_FUNCTION(column_titles_active);
+// The column titles can be pressed
+SIMPLE_FUNCTION(column_titles_passive);
+// The column titles can't be pressed
+
+SIMPLE_INT_FUNCTION(column_title_active);
+NAME_ARGS(column);
+// Make a specific column title active
+
+SIMPLE_INT_FUNCTION(column_title_passive);
+NAME_ARGS(column);
+// Make a specific column title passive
+
+COMPLEX_FUNCTION(set_column_title, int, string);
+NAME_ARGS(column,title);
+// Set the column title of a specified column. It is a good idea to
+// set the titles before the column title buttons are shown.
+
+string COMPLEX_FUNCTION(get_column_title, int );
+NAME_ARGS(column);
+// Returns the title of a specified column.
+COMPLEX_FUNCTION(set_column_widget, int, widget);
+NAME_ARGS(column,widget);
+// Put a widget as a column title. The widget will be added to a
+// W(Button).
+
+widget COMPLEX_FUNCTION(get_column_widget, int );
+NAME_ARGS(column);
+// Return the widget for the specified column title
+COMPLEX_FUNCTION(set_column_visibility, int, int);
+NAME_ARGS(column,visiblep);
+// Hide or show a column
+COMPLEX_FUNCTION(set_column_resizeable, int, int);
+NAME_ARGS(column,resizeablep);
+// Make a column resizable, or remove it's the resizability.
+
+COMPLEX_FUNCTION(set_column_auto_resize, int, int);
+NAME_ARGS(column,autoresizep);
+// Automatically resize a column to the width of it's widest contents.
+
+int COMPLEX_FUNCTION(columns_autosize);
+// Resize all columns according to their contents
+int COMPLEX_FUNCTION(optimal_column_width, int);
+NAME_ARGS(column);
+// Return the optimal width of the specified column
+
+COMPLEX_FUNCTION(set_column_justification, int, int);
+NAME_ARGS(column,justification);
+// justification is one of CONST(GTK_JUSTIFY)
+
+COMPLEX_FUNCTION(set_column_width, int, int);
+NAME_ARGS(column,width);
+// Width in pixels
+COMPLEX_FUNCTION(set_column_min_width, int, int);
+NAME_ARGS(column,width);
+// Width in pixels
+
+COMPLEX_FUNCTION(set_column_max_width, int, int);
+NAME_ARGS(column,width);
+// if width < 0 , there is no restriction
+
+SIMPLE_INT_FUNCTION(set_row_height);
+NAME_ARGS(pixels);
+// in pixels
+
+COMPLEX_FUNCTION(moveto, int, int,float,float);
+NAME_ARGS(row,column,xpos,ypos);
+// Make the specified row and column visible, and place it relative to
+// xpos and ypos in the area the Clist occupies.  <p> xpos and ypos
+// are relative, 0.0 == top, 1.0 == bottom
+
+int COMPLEX_FUNCTION(get_cell_type, int, int);
+NAME_ARGS(row, column);
+// Return value is one of CONST(GTK_CELL)
+
+COMPLEX_FUNCTION(set_text, int, int, string);
+NAME_ARGS(row,column,text);
+// Set the text for the specified cell. Please note that even if auto
+// sorting is enabled, the row will not be resorted. Use the 'sort()'
+// function.
+FUNCTION(get_text, "function(int,int:string)");
+NAME_ARGS( row, column );
+// Return the text associated with a specific cell.
+{
+  int x, y;  
+  gchar *p = NULL;
+  get_all_args( "get_*", args, "%d%d", &x, &y );
+
+  pop_n_elems( args );
+  gtk_clist_get_text( GTK_CLIST( THIS->obj ), x, y, &p );
+  if(p)
+    push_text(p);
+  else
+    push_int(0);
+}
+
+
+
+FUNCTION(set_pixmap, "function(int,int,object,object|void:object)");
+ARGS(int,int,GDK.Pixmap,void|object(GDK.Bitmap));
+RETURNS(GTK.Clist);
+NAME_ARGS(row,column,image,mask);
+// Set the pixmap of the specified cell. The mask is optional
+{
+  int x, y;
+  struct object *a, *b=0;
+  GdkPixmap *img;
+  GdkBitmap *mask = NULL;
+  if(args == 3)
+    get_all_args("set_pixmap", args, "%d%d%o", &y,&x,&a );
+  else
+    get_all_args("set_pixmap", args, "%d%d%o%o", &y,&x,&a,&b );
+
+  img = get_gdkobject( a, Pixmap );
+  if(b) mask = get_gdkobject( b, Bitmap );
+  
+  gtk_clist_set_pixmap( GTK_CLIST( THIS->obj ), y, x, img, mask );
+
+  RETURN_THIS();
+}
+
+FUNCTION(get_pixmap, "function(int,int:mapping)");
+NAME_ARGS( row, column );
+// Return the pixmap for the specified cell
+{
+  int x, y;  
+  GdkPixmap *p = NULL;
+  GdkBitmap *b = NULL;
+  get_all_args( "get_*", args, "%d%d", &x, &y );
+
+  pop_n_elems( args );
+  gtk_clist_get_pixmap( GTK_CLIST( THIS->obj ), x, y, &p, &b );
+  push_text( "pixmap" );
+  if(p)
+  {
+    push_gdkobject(p, Pixmap);
+    gdk_pixmap_ref( p );
+  }
+  else
+    push_int( 0 );
+  push_text( "mask" );
+  if(b)
+  {
+    push_gdkobject(b, Bitmap);
+    gdk_bitmap_ref( b );
+  }
+  else
+    push_int( 0 );
+  f_aggregate_mapping( 2 );
+}
+
+
+
+
+FUNCTION(set_pixtext, "function(int,int,string,int,object,object|void:object)")
+ARGS(int,int,string,int,GDK.Pixmap,void|object(GDK.Bitmap));
+RETURNS(GTK.Clist);
+NAME_ARGS(row,column,text,spacing,image,mask);
+// Set the pixmap and text of the specified cell. The mask is optional
+// The spacing is the number of pixels between the pixmap and the text.
+{
+  int x, y;
+  struct object *a, *b=0;
+  char *t;
+  int s;
+  GdkPixmap *img;
+  GdkBitmap *mask = NULL;
+  if(args == 5)
+    get_all_args("set_pixmap", args, "%d%d%s%d%o", &y,&x, &t, &s, &a );
+  else
+    get_all_args("set_pixmap", args, "%d%d%s%d%o%o", &y,&x, &t, &s,&a,&b );
+
+  img = get_gdkobject( a, Pixmap );
+  if(b) mask = get_gdkobject( b, Bitmap );
+  
+  gtk_clist_set_pixtext( GTK_CLIST( THIS->obj ), y, x, t,s, img, mask );
+
+  RETURN_THIS();
+}
+
+FUNCTION(get_pixtext, "function(int,int:mapping)");
+NAME_ARGS( row, column );
+// Return the pixmap and text for the specified cell as a mapping:<br>
+// ([ "spacing":spacing, "text":text, "pixmap":pixmap ])
+{
+  int x, y;  
+  gchar *t = NULL;
+  GdkPixmap *p = NULL;
+  GdkBitmap *b = NULL;
+  guint8 s = 0;
+  get_all_args( "get_*", args, "%d%d", &x, &y );
+
+  gtk_clist_get_pixtext( GTK_CLIST( THIS->obj ), x, y, &t, &s, &p, &b );
+  pop_n_elems( args );
+
+  push_text( "spacing" );
+  push_int( s );
+
+  push_text( "text" );
+  if(t)
+    push_text( t );
+  else
+    push_int( 0 );
+  push_text( "pixmap" );
+  if(p)
+  {
+    push_gdkobject(p, Pixmap);
+    gdk_pixmap_ref( p );
+  }
+  else
+    push_int( 0 );
+  push_text( "mask" );
+  if(b)
+  {
+    push_gdkobject(b, Bitmap);
+    gdk_bitmap_ref( b );
+  }
+  else
+    push_int( 0 );
+
+  f_aggregate_mapping( 8 );
+}
+
+
+FUNCTION(set_foreground, "function(int,object:object)")
+ARGS(int,GDK.Color);
+RETURNS(GTK.Clist);
+NAME_ARGS(row,color);
+// Set the foreground color of the specified row to the specified color
+{
+  struct object *a;
+  int row;
+  GdkColor *c;
+  get_all_args( "set_foreground", args, "%d%o", &row, &a );
+  c = get_gdkobject( a, Color );
+  gtk_clist_set_foreground( GTK_CLIST( THIS->obj ), row, c );
+
+  RETURN_THIS();
+}
+
+FUNCTION(set_background, "function(int,object:object)")
+ARGS(int,GDK.Color);
+RETURNS(GTK.Clist);
+NAME_ARGS(row,color);
+// Set the background color of the specified row the the specified color
+{
+  struct object *a;
+  int row;
+  GdkColor *c;
+  get_all_args( "set_background", args, "%d%o", &row, &a );
+  c = get_gdkobject( a, Color );
+  gtk_clist_set_background( GTK_CLIST( THIS->obj ), row, c );
+
+  RETURN_THIS();
+}
+
+COMPLEX_FUNCTION(set_cell_style, int, int, style );
+NAME_ARGS(row,column,style);
+// Set a W(Style) for a specific cell
+style COMPLEX_FUNCTION(get_cell_style, int, int );
+NAME_ARGS(row,col);
+// return the W(Style) associated with a specific cell
+COMPLEX_FUNCTION(set_row_style, int, style );
+NAME_ARGS(row,style);
+style COMPLEX_FUNCTION(get_row_style, int );
+NAME_ARGS(row);
+// Return the W(style) object associated with the specified row
+COMPLEX_FUNCTION(set_shift, int, int, int, int);
+NAME_ARGS(row,column,yshift,xshift);
+// The contents of the specified cell will be drawn shifted (indented)
+// the specifid number of pixels.
+// <p>
+// This can be useful to generate a tree-like layout when you do not
+// want to make a W(Ctree)
+COMPLEX_FUNCTION(set_selectable, int, int);
+NAME_ARGS(row, selectablep);
+// If true, the row can be selected by the user, otherwise it cannot
+// be selected, only focused.
+int COMPLEX_FUNCTION(get_selectable, int);
+NAME_ARGS(row);
+// Return 1 if the specified row can be selected by the user.
+int COMPLEX_FUNCTION(append, stringarray/GTK_CLIST{THIS->obj}->columns);
+NAME_ARGS(columns);
+//  The return value of indicates the index of the row that was just
+//  added.
+// <p>
+// 'columns' are the texts we want to put in the columns. The size of
+// the array should equal the number of columns in the list.
+
+int COMPLEX_FUNCTION(prepend, stringarray/GTK_CLIST{THIS->obj}->columns);
+NAME_ARGS(columns);
+//  The return value of indicates the index of the row that was just
+//  added.
+// <p>
+// 'columns' are the texts we want to put in the columns. The size of
+// the array should equal the number of columns in the list.
+
+int COMPLEX_FUNCTION(insert, int, stringarray/GTK_CLIST{THIS->obj}->columns);
+NAME_ARGS(row,columns);
+// Insert a row after a specified row.<p>
+//  The return value of indicates the index of the row that was just
+//  added, please note that this is not nessasarily the same row as
+//  the specified one, if autosort is activated, the row will be
+//  inserted so that the list is sill sorted.
+// <p>
+// 'columns' are the texts we want to put in the columns. The size of
+// the array should equal the number of columns in the list.
+
+COMPLEX_FUNCTION(remove, int);
+NAME_ARGS(row);
+// Delete a specified row. If you want to remove all rows in a Clist,
+// use 'clear()' instead of calling remove multiple times.
+
+static void freeit(struct object *o)
+{
+  free_object( o );
+}
+
+FUNCTION(set_row_data, "function(int,object:void)");
+NAME_ARGS(row,data);
+// Set the user data associated with the specified row.
+// This data can be used to find rows, and when a row is selected it
+// can be easily retrieved using node_get_row_data.
+// <p>
+// <b>You can only use objects as row data right now</b>
+{
+  int row;
+  struct object *obj;
+  get_all_args( "set_row_data", args, "%d%o", &row, &obj );
+ add_ref(obj);
+  gtk_clist_set_row_data_full( GTK_CLIST( THIS->obj ), row, obj, 
+                               (void *)freeit );
+  RETURN_THIS();
+}
+
+FUNCTION(get_row_data, "function(int:object)");
+NAME_ARGS(row);
+// Return the data associated with a row, or 0.
+{
+  int row;
+  struct object *o;
+  get_all_args( "get_row_data", args, "%d", &row );
+
+  o = gtk_clist_get_row_data( GTK_CLIST( THIS->obj ), row );
+  pop_n_elems( args );
+  if(o)
+    ref_push_object( o );
+  else
+    push_int( 0 );
+}
+
+FUNCTION(find_row_from_data, "function(object:int)");
+NAME_ARGS(data);
+// Find a row in the list that has the given user data.  If no node is
+// found, 0 is returned.
+{
+  int row;
+  struct object *o;
+  get_all_args( "find_row_from_data", args, "%o", &o );
+  row = gtk_clist_find_row_from_data( GTK_CLIST( THIS->obj ), o );
+  pop_n_elems(args);
+  push_int( row );
+}
+
+COMPLEX_FUNCTION(select_row, int, int);
+NAME_ARGS(row,column);
+// Select the given row. The column is sent to the signal handler, but
+// ignored for all other purposes.
+
+
+COMPLEX_FUNCTION(unselect_row, int, int);
+NAME_ARGS(row,column);
+// Unselect the given row. The column is sent to the signal handler,
+// but ignored for all other purposes.
+
+SIMPLE_FUNCTION(undo_selection);
+// Undo the previous selection
+SIMPLE_FUNCTION(clear);
+// remove all rows
+
+FUNCTION(get_selection_info, "function(int,int:mapping)");
+NAME_ARGS(x,y);
+RETURNS(mapping(string:int));
+// return the row column corresponding to the x and y coordinates,
+// the returned values are only valid if the x and y coordinates
+// are relative to the clist window coordinates
+{
+  int r=-1, c=-1, x, y;
+  get_all_args( "get_selection_info", args, "%d%d", &x, &y );
+  gtk_clist_get_selection_info( GTK_CLIST( THIS->obj ), x, y, &r, &c );
+
+  pop_n_elems( args );
+  push_text( "row" );
+  push_int( r );
+  push_text( "column" );
+  push_int( c );
+  f_aggregate_mapping( 4 );
+}
+
+SIMPLE_FUNCTION(select_all);
+// Select all rows
+SIMPLE_FUNCTION(unselect_all);
+// Unselect all rows
+
+COMPLEX_FUNCTION(row_move, int, int);
+NAME_ARGS(from_row, to_row);
+// Move the specified row to just before the specified destination
+// row.
+
+FUNCTION(get_foreground, "function(int:object)");
+RETURNS(GDK.Color);
+NAME_ARGS(row);
+// Return the foregroun color for the specified row
+{
+  GtkCListRow *clist_row;
+  GtkCList *clist = GTK_CLIST( THIS->obj );
+  GtkStyle *style;
+  int row;
+  get_all_args("get_foreground", args, "%d", &row );
+  pop_n_elems(args);
+  if (row < 0 || row >= clist->rows)
+    error("Invalid row.\n");
+  clist_row = (g_list_nth (clist->row_list, row))->data;
+  if( clist_row->fg_set )
+  {
+    push_gdkobject( (void *)&clist_row->foreground, Color );
+    return;
+  }  else if( (style = clist_row->style) ) {
+    push_gdkobject( (void *)&style->fg[GTK_STATE_NORMAL], Color );
+    return;
+  }  else if( (style = clist->container.widget.style) ) {
+    push_gdkobject( (void *)&style->fg[GTK_STATE_NORMAL], Color );
+    return;
+  } else {
+    push_int( 0 );
+    return;
+  }
+}
+
+FUNCTION(get_background, "function(int:object)");
+RETURNS(GDK.Color);
+NAME_ARGS(row);
+// Return the background color of a specified row
+{
+  GtkCListRow *clist_row;
+  GtkCList *clist = GTK_CLIST( THIS->obj );
+  GtkStyle *style;
+  int row;
+  get_all_args("get_background", args, "%d", &row );
+  pop_n_elems(args);
+  if (row < 0 || row >= clist->rows)
+    error("Invalid row.\n");
+  clist_row = (g_list_nth (clist->row_list, row))->data;
+  if( clist_row->bg_set )
+  {
+    push_gdkobject( &clist_row->background, Color );
+    return;
+  }  else if( (style = clist_row->style) ) {
+    push_gdkobject( &style->base[GTK_STATE_ACTIVE], Color );
+    return;
+  } else if( (style = clist->container.widget.style) ) {
+    push_gdkobject( (void *)&style->base[GTK_STATE_ACTIVE], Color );
+    return;
+  } else {
+    push_int( 0 );
+  }
+}
+
+static gint please_do_compare_with_pike_func( GtkCList *clist,
+                                              GtkCListRow *row1,
+                                              GtkCListRow *row2 )
+{
+  /* 
+     Asume we are called from a thread that started it's life in pike.
+     Also asume that we have the interpreter lock.
+     Otherwise, we are toasted. Really toasted.
+     We could of course start a new thread here for just the compare 
+     function. That might not be desireable.
+  */
+  int ret;
+  struct svalue *sf = gtk_object_get_data(GTK_OBJECT(THIS->obj), 
+                                          "pike_clist_sort_fun");
+  struct svalue *op = sp;
+
+  if(!sf)
+    return 1;
+
+  push_constant_text( "clist" );
+  push_gtkobjectclass( clist, pgtk_clist_program );
+
+  push_constant_text( "sort_column" );
+  push_int( clist->sort_column );
+
+  push_constant_text( "row1_data" );
+  if( row1->data )
+    ref_push_object( (struct object *)row1->data );
+  else
+    push_int( 0 );
+
+  push_constant_text( "row2_data" );
+  if( row2->data )
+    ref_push_object( (struct object *)row2->data );
+  else
+    push_int( 0 );
+
+
+  push_constant_text( "row1_text" );
+  switch(row1->cell[clist->sort_column].type)
+  {
+    case GTK_CELL_PIXTEXT:
+      push_text(GTK_CELL_PIXTEXT (row1->cell[clist->sort_column])->text);
+      break;
+    case GTK_CELL_TEXT:
+      push_text(GTK_CELL_TEXT (row1->cell[clist->sort_column])->text);
+      break;
+   default:
+     push_int(0);
+  }
+
+  push_constant_text( "row2_text" );
+  switch(row2->cell[clist->sort_column].type)
+  {
+    case GTK_CELL_PIXTEXT:
+      push_text(GTK_CELL_PIXTEXT (row2->cell[clist->sort_column])->text);
+      break;
+    case GTK_CELL_TEXT:
+      push_text(GTK_CELL_TEXT (row2->cell[clist->sort_column])->text);
+      break;
+   default:
+     push_int(0);
+  }
+
+
+  f_aggregate_mapping( sp-op );
+  apply_svalue( sf, 1 );
+  ret = sp[-1].u.integer;
+  pop_stack();
+  return ret;
+}
+
+static struct svalue *my_dup_svalue( struct svalue *s )
+{
+  struct svalue *res;
+  res = malloc(sizeof(struct svalue));
+  assign_svalue_no_free( res, s );
+  return res;
+}
+
+static void my_free_svalue( struct svalue *s )
+{
+  free_svalue( s );
+  free( s );
+}
+
+FUNCTION(set_compare_func, "function(function|void:object)");
+NAME_ARGS(cmpfun);
+// Set the compare function. The function will be called with a
+// mapping as it's only argument, like this:<br><pre>
+// &nbsp; ([
+// &nbsp;    "clist":the clist widget,
+// &nbsp;    "sort_column":the column to sort on,
+// &nbsp;    "row1_data":The user data pointer for the first row,
+// &nbsp;    "row2_data":The user data pointer for the second row,
+// &nbsp;    "row1_text":The text in the sort cell in the first row
+// &nbsp;    "row2_text":The text in the sort cell in the second row
+// &nbsp: ])
+// </pre>
+// The return value is one of:<p>
+//   1: Row 1 is more than row 2<br>
+//   0: The rows are equal<br>
+//  -1: Row 1 is lesser than row 2<br>
+{
+  if(IS_ZERO(sp-1))
+  {
+    gtk_object_remove_data( THIS->obj, "pike_clist_sort_fun" );
+    gtk_clist_set_compare_func( GTK_CLIST( THIS->obj ), NULL );
+  } else {
+    gtk_object_set_data_full(THIS->obj, "pike_clist_sort_fun",
+                             (void*)my_dup_svalue(sp-1), (void*)my_free_svalue);
+    gtk_clist_set_compare_func( GTK_CLIST( THIS->obj ), 
+                                (void *)please_do_compare_with_pike_func );
+  }
+  RETURN_THIS();
+}
+
+FUNCTION(get_selection, "function(void:array)");
+RETURNS(array(int));
+// Return an array with all selected rows.
+{
+  GList *work = GTK_CLIST(THIS->obj)->selection;
+  int nelems = 0;
+  while( work )
+  {
+    push_int( (int)( work->data ) );
+    work = work->next;
+    nelems++;
+  }
+  f_aggregate( nelems );
+}
+
+COMPLEX_FUNCTION(set_sort_type, int);
+NAME_ARGS( direction );
+// Ascending or descending (One of CONST(GTK_SORT))
+COMPLEX_FUNCTION(set_sort_column, int);
+NAME_ARGS(column);
+COMPLEX_FUNCTION(sort);
+// Set the column on which all sorting will be performed
+COMPLEX_FUNCTION(set_auto_sort, int);
+NAME_ARGS( sortp );
+// If true, the clist will automatically be re-sorted when new rows
+// are inserted. Please note that it will not be resorted if the text
+// in cells are changed, use 'sort()' to force a reorder. The sort
+// function is stable.
+
+CLASSMEMBER(shadow_type, int);
+// Return the curreent shadow type. One of CONST(GTK_SHADOW)
+CLASSMEMBER(selection_mode, int);
+// Return the selection mode. One of CONST(GTK_SELECTION)
+CLASSMEMBER(drag_button, int);
+// Return the button used to drag items (by default 1)
+CLASSMEMBER(focus_row, int);
+// The currently focused row
+CLASSMEMBER(sort_type, int);
+// The sort method, one of CONST(GTK_SORT)
+CLASSMEMBER(sort_column, int);
+// The column that will be used to sort the rows
+CLASSMEMBER(flags, int);
+// Return the flags. A bitwise or of CONST(GTK_CLIST_)
+CLASSMEMBER(rows, int);
+// Return the number of rows
+CLASSMEMBER(row_height, int);
+// Return the height of the row
+CLASSMEMBER(row_center_offset, int);
+// Return the number of pixels from the top of the row to the center
+// of the row.
+CLASSMEMBER(columns, int);
+// Return the number of columns in this clist
diff --git a/src/post_modules/GTK/source/gtkcolorselection.pre b/src/post_modules/GTK/source/gtkcolorselection.pre
new file mode 100644
index 0000000000000000000000000000000000000000..bef902abefe678d230270e5a202d1dc0c08e1bd4
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkcolorselection.pre
@@ -0,0 +1,83 @@
+PROGRAM(color_selection);
+// The color selection widget is, not surprisingly, a widget for
+// interactive selection of colors.  This composite widget lets the
+// user select a color by manipulating RGB (Red, Green, Blue) and HSV
+// (Hue, Saturation, Value) triples. This is done either by adjusting
+// single values with sliders or entries, or by picking the desired
+// color from a hue-saturation wheel/value bar.  Optionally, the
+// opacity of the color can also be set.
+
+// <p>
+
+
+// The color selection widget currently emits only one signal,
+// "color_changed", which is emitted whenever the current color in the
+// widget changes, either when the user changes it or if it's set
+// explicitly through set_color().
+
+// <p>
+
+// IMG: GTK.ColorSelection()
+INHERIT(vbox);
+COMPLEX_FUNCTION(create);
+// Create a new color selection.
+COMPLEX_FUNCTION(set_update_policy,int);
+NAME_ARGS(policy);
+// one of CONST(GTK_UPDATE).
+// <p>
+// The default policy is GTK.UpdateContinuous which means that the
+// current color is updated continuously when the user drags the
+// sliders or presses the mouse and drags in the hue-saturation wheel
+// or value bar. If you experience performance problems, you may want
+// to set the policy to GTK.UpdateDiscontinuous or GTK.UpdateDelayed.
+
+COMPLEX_FUNCTION(set_opacity,int);
+NAME_ARGS(opacity);
+// The color selection widget supports adjusting the opacity of a
+// color (also known as the alpha channel). This is disabled by
+// default. Calling this function with use_opacity set to 1 enables
+// opacity. Likewise, use_opacity set to 0 will disable opacity.
+
+FUNCTION(get_color, "function(void:array(float))")
+//  When you need to query the current color, typically when you've
+//  received a "color_changed" signal, you use this function. The
+//  return value is an array of floats, See the set_color() function
+//  for the description of this array.
+{
+  double vals[4];
+  int i;
+  gtk_color_selection_get_color( GTK_COLOR_SELECTION( THIS->obj ), vals );
+  for(i=0; i<4; i++)
+    push_float(vals[i]);
+  f_aggregate( 4 );
+}
+
+FUNCTION(set_color, "function(array(float):object)")
+NAME_ARGS(rgba);
+RETURNS(GTK.ColorDialog);
+// You can set the current color explicitly by calling this function
+// with an array of colors (floats). The length of the array depends
+// on whether opacity is enabled or not. Position 0 contains the red
+// component, 1 is green, 2 is blue and opacity is at position 3 (only
+// if opacity is enabled, see set_opacity()) All values are between
+// 0.0 and 1.0
+{
+  gdouble vals[4];
+  int i;
+  struct array *a;
+  get_all_args( "set_color", args, "%a", &a );
+  for(i=0; i<a->size; i++)
+    if(i>3) 
+      break;
+    else
+      vals[i] = a->item[i].u.float_number;
+  gtk_color_selection_set_color( GTK_COLOR_SELECTION( THIS->obj ), vals );
+  
+  RETURN_THIS();
+}
+/*
+ * SUBWIDGET( wheel_area, container );
+ * SUBWIDGET( value_area, container );
+ * SUBWIDGET( sample_area, container );
+ * SUBWIDGET( sample_area_eb, container );
+ */
diff --git a/src/post_modules/GTK/source/gtkcolorselectiondialog.pre b/src/post_modules/GTK/source/gtkcolorselectiondialog.pre
new file mode 100644
index 0000000000000000000000000000000000000000..71d43b37012536f8a0babd26b5d0ddff17cfe7dd
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkcolorselectiondialog.pre
@@ -0,0 +1,21 @@
+PROGRAM(color_selection_dialog);
+// The color selection dialog widget is, not surprisingly, a color selection
+// widget in a dialog window. Use the subwidget functions below to access the
+// different subwidgets directly.
+// <p>
+// TIMG: GTK.ColorSelectionDialog("Select color")
+SIGNAL("color_changed", "Called when the color is changed");
+INHERIT(window);
+COMPLEX_FUNCTION(create,string);
+NAME_ARGS(title);
+// Create a new color selection dialog with the specified title.
+SUBWIDGET(colorsel, color_selection);
+// Return the color selection widget
+SUBWIDGET(ok_button, button);
+// Return the ok button
+SUBWIDGET(cancel_button, button);
+// Return the cancel button widget.
+SUBWIDGET(reset_button, button);
+// Return the reset button
+SUBWIDGET(help_button, button);
+// Return the help button
diff --git a/src/post_modules/GTK/source/gtkcombo.pre b/src/post_modules/GTK/source/gtkcombo.pre
new file mode 100644
index 0000000000000000000000000000000000000000..265554e3687e7c61b06ae22e809cd49004bac60b
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkcombo.pre
@@ -0,0 +1,86 @@
+PROGRAM(combo);
+// Thee combo box is another fairly simple widget that is really just
+// a collection of other widgets. From the user's point of view, the
+// widget consists of a text entry box and a pull down menu from which
+// the user can select one of a set of predefined
+// entries. Alternatively, the user can type a different option
+// directly into the text box.
+// <p>
+// The combo box has two principal parts that you as the programmer
+// really care about: The W(entry) and the W(list).
+// <p>
+// IMG: GTK.Combo()
+INHERIT(hbox);
+COMPLEX_FUNCTION(create);
+// Create a new combo box
+COMPLEX_FUNCTION(set_value_in_list, int, int);
+NAME_ARGS(value_must_be_in_list,ok_if_empty);
+// If value_must_be_in_list is true, the user will not be able to
+// enter any value that is not in the list. If ok_if_empty is true,
+// empty values are possible as well as the values in the list.
+
+COMPLEX_FUNCTION(set_use_arrows, int);
+NAME_ARGS(use_arrows);
+// set_use_arrows() lets the user change the value in the entry using
+// the up/down arrow keys. This doesn't bring up the list, but rather
+// replaces the current text in the entry with the next list entry (up
+// or down, as your key choice indicates). It does this by searching
+// in the list for the item corresponding to the current value in the
+// entry and selecting the previous/next item accordingly. Usually in
+// an entry the arrow keys are used to change focus (you can do that
+// anyway using TAB). Note that when the current item is the last of
+// the list and you press arrow-down it changes the focus (the same
+// applies with the first item and arrow-up).
+
+COMPLEX_FUNCTION(set_use_arrows_always, int);
+NAME_ARGS(always_arrows);
+// set_use_arrows_always() allows the use the the up/down arrow keys
+// to cycle through the choices in the dropdown list, just as with
+// set_use_arrows, but it wraps around the values in the list,
+// completely disabling the use of the up and down arrow keys for
+// changing focus.
+
+COMPLEX_FUNCTION(set_case_sensitive, int);
+NAME_ARGS(sensitivep);
+// set_case_sensitive() toggles whether or not GTK searches for
+// entries in a case sensitive manner. This is used when the Combo
+// widget is asked to find a value from the list using the current
+// entry in the text box. This completion can be performed in either a
+// case sensitive or insensitive manner, depending upon the use of
+// this function. The Combo widget can also simply complete the
+// current entry if the user presses the key combination MOD-1 and
+// "Tab". MOD-1 is often mapped to the "Alt" key, by the xmodmap
+// utility. Note, however that some window managers also use this key
+// combination, which will override its use within GTK.
+
+COMPLEX_FUNCTION(set_item_string, item, string);
+NAME_ARGS(item,text);
+// The item is one of the ones in the list subwidget.
+FUNCTION(set_popdown_strings, "function(array:object)" );
+RETURNS(GTK.Combo);
+NAME_ARGS(popdows_strings);
+// Set the values in the popdown list.
+{
+  GList *s = NULL;
+  struct array *a;
+  int i;
+  get_all_args("set_popdown_strings", args, "%a", &a);
+  for(i=0; i<a->size; i++)
+    if(a->item[i].type == T_STRING)
+      s = g_list_append( s, a->item[i].u.string->str );
+  if(!s)
+    error("No items in list!\n");
+  gtk_combo_set_popdown_strings( GTK_COMBO( THIS->obj ), s );
+  g_list_free( s );
+
+  RETURN_THIS();
+}
+
+SIMPLE_FUNCTION(disable_activate);
+// This will disable the 'activate' signal for the entry widget in the
+// combo box.
+
+SUBWIDGET(entry, entry);
+// The entry widget
+SUBWIDGET(list, list);
+// The list widget, contains the list of choices as W(Label) widgets.
diff --git a/src/post_modules/GTK/source/gtkcontainer.pre b/src/post_modules/GTK/source/gtkcontainer.pre
new file mode 100644
index 0000000000000000000000000000000000000000..b5c2f034746ea71ec350673733f862b070c39e82
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkcontainer.pre
@@ -0,0 +1,78 @@
+/* -*- c -*- */
+
+PROGRAM(container)
+// The basic container class.
+SIGNAL("add", "Called when a new object is added to the container. (used internally)");
+SIGNAL("remove", "Called when a object is removed from the container (used internally)");
+SIGNAL("need_resize", "Called when the container needs resizing (used internally)");
+SIGNAL("focus", "Called when the container gets focus (used internally)");
+SIGNAL("set_focus_child", "");
+INHERIT(widget);
+SIMPLE_INT_FUNCTION(set_border_width);
+NAME_ARGS(external_border_width);
+// Set the border width. The border width is the size of the 
+// padding around the container.
+// Calling this function might result in a resize of the container.
+#ifndef gtk_container_border_width
+# define gtk_container_border_width gtk_container_set_border_width 
+#endif
+SIMPLE_INT_FUNCTION(border_width);
+NAME_ARGS(width);
+// Compatibility alias for set_border_width.
+SIMPLE_WIDGET_FUNCTION(add);
+NAME_ARGS(widget);
+// Add a subwidget to the container. Don't forget to call show() in 
+// the subwidget. Some (even most) containers can only contain one child.
+// Calling this function might result in a resize of the container.
+SIMPLE_WIDGET_FUNCTION(remove);
+NAME_ARGS(widget);
+// Remove a child from the container. The argument is the child to remove.
+// Calling this function might result in a resize of the container.
+/* SIMPLE_FUNCTION(disable_resize); */
+/* // Stop all automatic resize actions */
+/* SIMPLE_FUNCTION(enable_resize); */
+/* // Enable all automatic resize actions */
+SIMPLE_INT_FUNCTION(set_resize_mode);
+NAME_ARGS(mode);
+// One of CONST(GTK_RESIZE)
+/* SIMPLE_FUNCTION(block_resize); */
+/* // (temporarily) disable all automatic resize actions */
+/* SIMPLE_FUNCTION(unblock_resize); */
+/* // reenable all automatic resize actions. */
+FUNCTION(children, "function(void:array(object))");
+RETURNS(array(GTK.Widget));
+// This function returns all children of the container
+// as an array.
+{
+  GList *g;
+  int n = 0;
+  pop_n_elems(args);
+  g = gtk_container_children( GTK_CONTAINER( THIS->obj ) );
+  while(g)
+  {
+    push_gtkobjectclass( GTK_OBJECT( g->data ), pgtk_widget_program );
+    n++;
+    g = g->next;
+  }
+  f_aggregate(n);
+}
+
+SIMPLE_WIDGET_FUNCTION(set_focus_child);
+NAME_ARGS(child);
+// Emulate a set_focus_child signal. Focus on the specified child.
+SIMPLE_ADJUSTMENT_FUNCTION(set_focus_vadjustment);
+NAME_ARGS(adj);
+// Set the vadjustment used to focus children.
+SIMPLE_ADJUSTMENT_FUNCTION(set_focus_hadjustment);
+NAME_ARGS(adj);
+// Set the hadjustment used to focus children.
+SIMPLE_INT_FUNCTION(focus);
+NAME_ARGS(focus_direction);
+// Emulate a focus event. direction is one of CONST(GTK_DIR_).
+SIMPLE_FUNCTION(register_toplevel);
+// Register this container as a toplevel widget.
+// Not normally called by applications
+SIMPLE_FUNCTION(unregister_toplevel);
+// Unregister this container as a toplevel widget.
+// Not normally called by applications
+
diff --git a/src/post_modules/GTK/source/gtkctree.pre b/src/post_modules/GTK/source/gtkctree.pre
new file mode 100644
index 0000000000000000000000000000000000000000..2ae3ccadd6b2623212eb4068d10a0ac152de4467
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkctree.pre
@@ -0,0 +1,577 @@
+PROGRAM(ctree);
+INHERIT(clist);
+// The GtkCTree widget is used for showing a hierarchical tree to the
+// user, for example a directory tree.
+// <p>
+// The tree is internally represented as a set of GtkCTreeNode
+// structures.
+// <p>
+// The interface has much in common with the GtkCList widget: rows
+// (nodes) can be selected by the user etc.
+// <p>
+// Positions in the tree are often indicated by two arguments, a
+// parent and a sibling, both GtkCTreeNode pointers. If the parent is
+// NULL, the position is at the root of the tree and if the sibling is
+// NULL, it will be the last child of parent, otherwise it will be
+// inserted just before the sibling.
+
+#define GtkCtreerow GtkCTreeRow
+#define GtkCtree GtkCTree
+
+#define pgtk_ctreenode_program pgtk_CTreeNode_program
+#define pgtk_ctreerow_program pgtk_CTreeRow_program
+#define GTK_CTREEROW(X) ((GtkCTreeRow *)X)
+#define GTK_CTREENODE(X) ((GtkCTreeNode *)X)
+#define GtkCtreenode GtkCTreeNode
+
+
+SIGNAL("tree_select_row", "Called when a node is selected.");
+SIGNAL("tree_unselect_row", "Called when a node is unselected.");
+SIGNAL("tree_expand", "Called when a node is expanded");
+SIGNAL("tree_collapse", "Called when a node is collapsed");
+SIGNAL("tree_move", "Called when a node is moved (using DND, as an example)");
+SIGNAL("change_focus_row_expansion", "Changed when the focused row is either expanded or collapsed");
+
+CLASSMEMBER(tree_indent,int);
+// The number of pixels to indent the tree levels.
+CLASSMEMBER(tree_spacing,int);
+// The number of pixels between the tree and the columns
+CLASSMEMBER(tree_column,int);
+// The column that is the tree column (the one with the expand/collapse icons)
+CLASSMEMBER(line_style,int);
+// The style of the lines, one of CONST(GTK_CTREE_LINES)
+CLASSMEMBER(expander_style,int);
+// The style of the expander buttons, one of CONST(GTK_CTREE_EXPANDER)
+CLASSMEMBER(show_stub,int);
+// Will stubs be shows?
+
+
+
+COMPLEX_FUNCTION(create,int,int);
+NAME_ARGS(columns,tree_column);
+// tree_column is the column that has the tree graphics (lines and
+// expander buttons).
+
+FUNCTION(insert_node, "function(object|void,object|void,array(string)|void,int,int:object)");
+NAME_ARGS(parent,sibling,text,is_leaf,expanded);
+ARGS(GTK.CTreeNode|void,GTK.CTreeNode|void,array(string)|void,int,int);
+RETURNS(GTK.CTreeNode);
+// At least one of parent or sibling must be specified.
+// If both are specified, sibling->parent() must be equal to parent.
+// <p>
+// If the parent and sibling is 0, the position is at the root of the
+// tree, if the sibling is NULL, it will be the last child of parent,
+// otherwise it will be inserted just before the sibling.
+// <p>
+{
+  GtkCTreeNode *parent = NULL, *sibling = NULL;
+  struct array *text = NULL;
+  gchar **text_arr = NULL;
+  int is_leaf, expanded;
+  
+  if(args < 5)
+    error("Too few arguments to insert_node\n");
+   
+  if(sp[-args].type == T_OBJECT)
+    parent = get_pgdkobject( sp[-args].u.object, pgtk_CTreeNode_program );
+  if(sp[-args+1].type == T_OBJECT)
+    sibling = get_pgdkobject( sp[-args].u.object, pgtk_CTreeNode_program );
+  if(sp[-args+2].type == T_ARRAY)
+    text = sp[-args+2].u.array;
+  is_leaf =sp[-args+3].u.integer;
+  expanded =sp[-args+4].u.integer;
+  
+  if(text)
+  {
+    int i;
+
+    if (GTK_CLIST(THIS->obj)->columns != text->size)
+       error("Argument 3 to insert_node (text) has wrong size (columns=%d, elements=%d)\n",GTK_CLIST(THIS->obj)->columns,text->size);
+
+    text_arr = alloca(GTK_CLIST(THIS->obj)->columns * sizeof(gchar *));
+    for(i=0; i<GTK_CLIST(THIS->obj)->columns; i++)
+      if(i<text->size && text->item[i].type == T_STRING)
+        text_arr[i] = text->item[i].u.string->str;
+      else
+        text_arr[i] = NULL;
+  }
+  sibling = gtk_ctree_insert_node( GTK_CTREE( THIS->obj),
+                                   parent,
+                                   sibling,
+                                   text_arr,
+                                   0,0,0,0,0,
+                                   is_leaf,
+                                   expanded);
+
+  pop_n_elems(args);
+  push_pgdkobject( sibling, pgtk_CTreeNode_program );
+}
+
+COMPLEX_FUNCTION(remove_node, ?CTreeNode);
+NAME_ARGS(node);
+// Remove a node and it's subnodes from the tree.
+// The nodes will be destroyed, so you cannot add them again.
+int COMPLEX_FUNCTION(is_viewable, ?CTreeNode);
+NAME_ARGS(node);
+// Returns 1 if a certain node can be viewed (with or without
+// scrolling of the tree).<p>
+// Returns 0 if the node is in a folded part of the tree. 
+CTreeNode COMPLEX_FUNCTION(last, ?CTreeNode);
+NAME_ARGS(node);
+// Returns the last child of the last child of the last child... of
+// the given node.
+CTreeNode COMPLEX_FUNCTION(find_node_ptr, ?CTreeRow);
+NAME_ARGS(node);
+// Given a W(CTreeRow) (deprectated structure in PiGTK), return the
+// W(CTreeNode) associated with the row.
+CTreeNode COMPLEX_FUNCTION(node_nth, int);
+NAME_ARGS(row);
+// Return the node that is currently visible on the specified row.
+int COMPLEX_FUNCTION(find, CTreeNode, ?CTreeNode);
+NAME_ARGS(node, start);
+// Returns true if the node is a child of the start node.
+// <br>If you omit the starting node, the tree will be searched from
+// the root.
+int COMPLEX_FUNCTION(is_ancestor, CTreeNode, CTreeNode);
+NAME_ARGS(node, child);
+// Returns true if <b>node</b> is an ancestor of <b>child</b>
+int COMPLEX_FUNCTION(is_hot_spot, int, int);
+NAME_ARGS(x,y);
+// Returns true if the given coordinates lie on an expander button
+COMPLEX_FUNCTION(move, CTreeNode, ?CTreeNode, ?CTreeNode);
+NAME_ARGS(node,new_parent,new_sibling);
+// Move a node. Coordinates work as for insert.
+
+COMPLEX_FUNCTION(expand, ?CTreeNode);
+NAME_ARGS(node);
+// Expand the node, showing it's children.
+// If no node is given, expand the toplevel of the tree
+COMPLEX_FUNCTION(expand_recursive, ?CTreeNode);
+NAME_ARGS(node);
+// Expand the node, showing it's children, it's childrens children, etc.
+// If no node is given, expand the whole tree
+COMPLEX_FUNCTION(expand_to_depth, ?CTreeNode, int);
+NAME_ARGS(node,depth);
+// Expand depth levels of the tree, starting with the specified node.
+// If no node is given, start with the toplevel node.
+COMPLEX_FUNCTION(collapse, ?CTreeNode);
+NAME_ARGS(node);
+// Collapse the node, hiding it's children.
+// If no node is given, expand the toplevel of the tree
+COMPLEX_FUNCTION(collapse_recursive, ?CTreeNode);
+NAME_ARGS(node);
+// Collapse the node, showing it's children, it's childrens children, etc.
+// If no node is given, collapse the whole tree
+COMPLEX_FUNCTION(collapse_to_depth, ?CTreeNode,int);
+NAME_ARGS(node,depth);
+// Collapse depth levels of the tree, starting with the specified node.
+// If no node is given, start with the toplevel node.
+COMPLEX_FUNCTION(toggle_expansion, ?CTreeNode);
+NAME_ARGS(node);
+// If the node is expanded, collapse it, and if it's collapsed, expand it.
+COMPLEX_FUNCTION(toggle_expansion_recursive, ?CTreeNode);
+NAME_ARGS(node);
+// Toggle the expansion of the whole subtree, starting with node.
+COMPLEX_FUNCTION(select, CTreeNode);
+NAME_ARGS(node);
+// Select a node.
+COMPLEX_FUNCTION(select_recursive, CTreeNode);
+NAME_ARGS(node);
+// Select a node and it's children.
+COMPLEX_FUNCTION(unselect, CTreeNode);
+NAME_ARGS(node);
+// Unselect a node.
+COMPLEX_FUNCTION(unselect_recursive, CTreeNode);
+NAME_ARGS(node);
+// Unselect a node and it's children.
+
+
+FUNCTION(find_by_row_data, "function(object,object|void:object)");
+NAME_ARGS(data,root);
+// Find a node in the tree starting with root, that has the given user data.
+// If no node is found, 0 is returned.
+{
+  struct object *o;
+  struct object *root = NULL;
+  GtkCTreeNode *row, *root_node = NULL;
+  if(args == 1)
+    get_all_args( "find_by_row_data", args, "%o", &o );
+  else
+    get_all_args( "find_by_row_data", args, "%o%o", &o, &root );
+  if(root)
+    root_node = get_pgdkobject( root, pgtk_CTreeNode_program );
+  row = gtk_ctree_find_by_row_data( GTK_CTREE( THIS->obj ), root_node, o );
+  pop_n_elems(args);
+
+  if(row == NULL)
+    push_int( 0 );
+  else
+    push_pgdkobject( row, pgtk_CTreeNode_program );
+}
+
+
+
+/*
+GList * gtk_ctree_find_all_by_row_data           (GtkCTree     *ctree,
+						  GtkCTreeNode *node,
+						  gpointer      data);
+
+GtkCTreeNode * gtk_ctree_find_by_row_data_custom (GtkCTree     *ctree,
+						  GtkCTreeNode *node,
+						  gpointer      data,
+						  GCompareFunc  func);
+
+void gtk_ctree_post_recursive                    (GtkCTree     *ctree, 
+						  GtkCTreeNode *node,
+						  GtkCTreeFunc  func,
+						  gpointer      data);
+void gtk_ctree_post_recursive_to_depth           (GtkCTree     *ctree, 
+						  GtkCTreeNode *node,
+						  gint          depth,
+						  GtkCTreeFunc  func,
+						  gpointer      data);
+void gtk_ctree_pre_recursive                     (GtkCTree     *ctree, 
+						  GtkCTreeNode *node,
+						  GtkCTreeFunc  func,
+						  gpointer      data);
+void gtk_ctree_pre_recursive_to_depth            (GtkCTree     *ctree, 
+						  GtkCTreeNode *node,
+						  gint          depth,
+						  GtkCTreeFunc  func,
+						  gpointer      data);
+*/
+
+COMPLEX_FUNCTION(node_set_text, CTreeNode, int, string);
+NAME_ARGS(node,column,text);
+// Set the text in a cell
+COMPLEX_FUNCTION(node_set_pixmap, CTreeNode, int, GdkPixmap, ?Gdkbitmap);
+NAME_ARGS(node,column,pixmap,mask);
+// Set the pixmap in a cell
+COMPLEX_FUNCTION(node_set_pixtext, CTreeNode, int, string, int, GdkPixmap, ?Gdkbitmap);
+NAME_ARGS(node,column,text,spacing,pixmap,mask);
+// Set the pixmap and text in a cell
+COMPLEX_FUNCTION(set_node_info, CTreeNode, string, int, ?GdkPixmap, ?GdkBitmap, ?GdkPixmap, ?GdkBitmap, int, int);
+NAME_ARGS(node,text,spacing,pixmap_closed,mask_closed,pixmap_opened,mask_opened,is_leaf,expanded);
+// <table>
+// <tr><td> text :</td><td>The texts to be shown in each column.</td></tr>
+// <tr><td>spacing :</td>
+// <td>The extra space between the pixmap and the text.</td></tr>
+// <tr><td>pixmap_closed :</td>
+// <td>The pixmap to be used when the node is collapsed. Can be NULL.</td></tr>
+// <tr><td> mask_closed :</td>
+// <td>The mask for the above pixmap. Can be NULL.</td></tr>
+// <tr><td> pixmap_opened :</td>
+// <td>The pixmap to be used when the children are visible. Can be NULL.</td></tr>
+// <tr><td>  mask_opened :</td>
+// <td>The mask for the above pixmap. Can be NULL.</td></tr>
+// <tr><td>is_leaf :</td>
+// <td>Whether this node is going to be a leaf.</td></tr>
+// <tr><td> expanded :</td>
+// <td>Whether this node should start out expanded or not.</td></tr>
+// </table>
+
+COMPLEX_FUNCTION(node_set_shift, CTreeNode, int, int, int);
+NAME_ARGS(node,column,vertical,horizontal);
+// Shift the given cell the given amounts in pixels.
+COMPLEX_FUNCTION(node_set_selectable, CTreeNode, int);
+NAME_ARGS(node,selectablep);
+// Whether this node can be selected by the user.
+int COMPLEX_FUNCTION(node_get_selectable, CTreeNode);
+NAME_ARGS(node);
+// Return whether or not this node can be selcted by the user
+int COMPLEX_FUNCTION(node_get_cell_type, CTreeNode, int);
+NAME_ARGS(node,column);
+// Return the celltype of this node.
+
+
+FUNCTION(node_get_text, "function(object,int:string)");
+NAME_ARGS( node, column );
+// Returns the text of the specified node
+{
+  struct object *x;
+  int y;  
+  gchar *p = NULL;
+  get_all_args( "get_*", args, "%o%d", &x, &y );
+
+  pop_n_elems( args );
+  gtk_ctree_node_get_text( GTK_CTREE( THIS->obj ), 
+                           get_pgdkobject(x,pgtk_CTreeNode_program), 
+                           y, &p );
+  if(p)
+    push_text(p);
+  else
+    push_int(0);
+}
+
+FUNCTION(node_get_pixmap, "function(object,int:mapping)");
+NAME_ARGS( row, column );
+// Returns the pixmap and mask of this node in a mapping:<br>
+// ([ "pixmap":the_pixmap, "mask":the_bitmap ])
+{
+  struct object *x;
+  int y;  
+  GdkPixmap *p = NULL;
+  GdkBitmap *b = NULL;
+  get_all_args( "get_*", args, "%d%d", &x, &y );
+
+  pop_n_elems( args );
+  gtk_ctree_node_get_pixmap( GTK_CTREE( THIS->obj ), 
+                             get_pgdkobject(x,pgtk_CTreeNode_program),
+                             y, &p, &b );
+  push_text( "pixmap" );
+
+  if(p)
+  {
+    push_gdkobject(p, Pixmap);
+    gdk_pixmap_ref( p );
+  }
+  else
+    push_int( 0 );
+  push_text( "mask" );
+  if(b)
+  {
+    push_gdkobject(b, Bitmap);
+    gdk_bitmap_ref( p );
+  }
+  else
+    push_int( 0 );
+  f_aggregate_mapping( 2 );
+}
+
+
+FUNCTION(node_get_pixtext, "function(object,int:mapping)");
+NAME_ARGS( row, column );
+// Returns the pixmap, mask and text of this node in a mapping:<br>
+// ([ "pixmap":the_pixmap, "mask":the_bitmap, "text":the_text ])
+{
+  struct object *x;
+  int y;  
+  gchar *t = NULL;
+  GdkPixmap *p = NULL;
+  GdkBitmap *b = NULL;
+  guint8 s = 0;
+  get_all_args( "get_*", args, "%d%d", &x, &y );
+
+  gtk_ctree_node_get_pixtext( GTK_CTREE( THIS->obj ), 
+                              get_pgdkobject(x,pgtk_CTreeNode_program),
+                              y, &t, &s, &p, &b );
+  pop_n_elems( args );
+
+  push_text( "spacing" );
+  push_int( s );
+
+  push_text( "text" );
+  if(t)
+    push_text( t );
+  else
+    push_int( 0 );
+  push_text( "pixmap" );
+  if(p)
+  {
+    push_gdkobject(p, Pixmap);
+    gdk_pixmap_ref( p );
+  }
+  else
+    push_int( 0 );
+  push_text( "mask" );
+  if(b)
+  {
+    push_gdkobject(b, Bitmap);
+    gdk_bitmap_ref( b );
+  }
+  else
+    push_int( 0 );
+
+  f_aggregate_mapping( 8 );
+}
+
+
+
+/*
+gint gtk_ctree_get_node_info                     (GtkCTree     *ctree,
+						  GtkCTreeNode *node,
+						  gchar       **text,
+						  guint8       *spacing,
+						  GdkPixmap   **pixmap_closed,
+						  GdkBitmap   **mask_closed,
+						  GdkPixmap   **pixmap_opened,
+						  GdkBitmap   **mask_opened,
+						  gboolean     *is_leaf,
+						  gboolean     *expanded);
+*/
+
+COMPLEX_FUNCTION(node_set_row_style, CTreeNode, style);
+NAME_ARGS(node,style);
+// Set the style of a row
+style COMPLEX_FUNCTION(node_get_row_style, CTreeNode);
+NAME_ARGS(node);
+// Return the style of a row
+COMPLEX_FUNCTION(node_set_cell_style, CTreeNode, int, style);
+NAME_ARGS(node,col,style);
+// Set the style of a cell
+style COMPLEX_FUNCTION(node_get_cell_style, CTreeNode,int);
+NAME_ARGS(node,col);
+// Return the style of a cell
+
+COMPLEX_FUNCTION(node_set_foreground, CTreeNode, GdkColor);
+NAME_ARGS(node,col);
+// Set the foreground of a row
+COMPLEX_FUNCTION(node_set_background, CTreeNode, GdkColor);
+NAME_ARGS(node,color);
+// Set the background of a row
+
+
+static void freeit(struct object *o)
+{
+  free_object( o );
+}
+
+FUNCTION(node_set_row_data, "function(object,object:void)");
+NAME_ARGS(node,data);
+// Set the user data associated with the specified node.
+// This data can be used to find nodes, and when a node is selected it
+// can be easily retrieved using node_get_row_data.
+// <p>
+// <b>You can only use objects as row data right now</b>
+{
+  struct object *row;
+  struct object *obj;
+  get_all_args( "set_row_data", args, "%o%o", &row, &obj );
+ add_ref(obj);
+  gtk_ctree_node_set_row_data_full( GTK_CTREE( THIS->obj ), 
+                                    get_pgdkobject(row,pgtk_CTreeNode_program), 
+                                    obj, 
+                                    (void *)freeit );
+  RETURN_THIS();
+}
+
+FUNCTION(node_get_row_data, "function(object:object)");
+NAME_ARGS(node);
+// Return the data associated with a node, or 0.
+{
+  struct object *row;
+  struct object *o;
+  get_all_args( "get_row_data", args, "%o", &row );
+
+  o = gtk_ctree_node_get_row_data( GTK_CTREE( THIS->obj ),  
+                                   get_pgdkobject(row,pgtk_CTreeNode_program));
+  pop_n_elems( args );
+  if(o)
+    ref_push_object( o );
+  else
+    push_int( 0 );
+}
+
+
+COMPLEX_FUNCTION(node_moveto, CTreeNode, int, float, float);
+NAME_ARGS(row,column,row_align,col_align);
+// Scroll the tree so a specified node (and column) is visible.
+// If the node is folded, it's first visible parent will be shown.
+
+int COMPLEX_FUNCTION(node_is_visible, CTreeNode);
+NAME_ARGS(node);
+// Return 1 if the node is currently visible
+COMPLEX_FUNCTION(set_indent, int);
+NAME_ARGS(npixels);
+// Set the indentation level
+COMPLEX_FUNCTION(set_spacing, int);
+NAME_ARGS(npixels);
+// Set the spacing between the tree column and the other columns
+COMPLEX_FUNCTION(set_show_stub, int);
+NAME_ARGS(stubp);
+// If true, the 'stub' will be shown. The stub is the small line that
+// goes horizontally from the expand or collapse button to the actual
+// contents of the tree
+
+COMPLEX_FUNCTION(set_line_style, int);
+NAME_ARGS(style);
+// Set the line style, one of CONST(GTK_CTREE_LINES)
+COMPLEX_FUNCTION(set_expander_style, int);
+NAME_ARGS(style);
+// Set the expander style, one of CONST(GTK_CTREE_EXPANDER)
+
+/*
+void gtk_ctree_set_drag_compare_func (GtkCTree     	      *ctree,
+				      GtkCTreeCompareDragFunc  cmp_func);
+*/
+
+COMPLEX_FUNCTION(sort_node, ?CTreeNode);
+NAME_ARGS(node);
+// Sort the specified node.
+COMPLEX_FUNCTION(sort_recursive, ?CTreeNode);
+NAME_ARGS(node);
+// Sort the specified node and it's children.
+
+
+PROGRAM(CTreeNode);
+// This is one of the nodes (branch or leaf) of the CTree.<br>
+// They are the equivalent of row numbers in a normal CList.
+#define GTK_CTREENODE(X) ((GtkCTreeNode *)X)
+FUNCTION(row, "function(void:object)");
+RETURNS(GTK.CTreeRow);
+// Returns the CTreeRow associated with this CTreeNode.<br>
+// <b>DEPRECATED</b>, all CTreeRow functions are also available
+// directly in this object.
+{
+  pop_n_elems(args);
+  push_pgdkobject( GTK_CTREE_ROW( THIS->obj ), pgtk_CTreeRow_program );
+}
+
+FUNCTION(parent, "function(void:object)");
+RETURNS(GTK.CTreeNode);
+// Returns the parent node
+{
+  pop_n_elems(args);
+  push_pgdkobject( GTK_CTREE_NODE(GTK_CTREE_ROW( THIS->obj )->parent), 
+                   pgtk_CTreeNode_program );
+}
+
+FUNCTION(child, "function(void:object)");
+RETURNS(GTK.CTreeNode);
+// Returns the first child node
+{
+  pop_n_elems(args);
+  push_pgdkobject( GTK_CTREE_NODE(GTK_CTREE_ROW( THIS->obj )->children), 
+                   pgtk_CTreeNode_program );
+}
+
+
+FUNCTION(next, "function(void:object)");
+RETURNS(GTK.CTreeNode);
+// Returns the next sibling (the next on the same  level)
+{
+  pop_n_elems(args);
+  push_pgdkobject( GTK_CTREE_NODE_NEXT( THIS->obj ), pgtk_CTreeNode_program );
+}
+
+FUNCTION(prev, "function(void:object)");
+RETURNS(GTK.CTreeNode);
+// Returns the previous sibling (the next on the same level)
+{
+  pop_n_elems(args);
+  push_pgdkobject( GTK_CTREE_NODE_PREV( THIS->obj ), pgtk_CTreeNode_program );
+}
+
+#undef  GTK_CTREENODE
+#define GTKCtreenode GtkCTreeRow
+#define GTK_CTREENODE(X) ((GtkCTreeRow *)X)
+CLASSMEMBER(level,int);
+// Returns the depth of this node in the tree
+CLASSMEMBER(is_leaf,int);
+// Is this node a leaf?
+CLASSMEMBER(expanded,int);
+// Is this node expanded?
+
+PROGRAM(CTreeRow);
+// This class is deprecated.
+#define GTK_CTREEROW(X) ((GtkCTreeRow *)X)
+SUBWIDGET(parent,CTreeNode);
+// Return the parent node of this node
+SUBWIDGET(children,CTreeNode);
+// Return the first child
+CLASSMEMBER(level,int);
+// Return the level of this node (0 for root, 1 for a child of the root, etc)
+CLASSMEMBER(is_leaf,int);
+// Return 1 if the node is a leaf node
+CLASSMEMBER(expanded,int);
+// Return 1 if the node is expanded
diff --git a/src/post_modules/GTK/source/gtkcurve.pre b/src/post_modules/GTK/source/gtkcurve.pre
new file mode 100644
index 0000000000000000000000000000000000000000..cfb1e7944990c2ec2be2582a422fbe36d26a2648
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkcurve.pre
@@ -0,0 +1,28 @@
+PROGRAM(curve);
+INHERIT(drawing_area);
+// IMG: GTK.Curve()
+COMPLEX_FUNCTION(create);
+SIMPLE_FUNCTION(reset);
+COMPLEX_FUNCTION(set_gamma,float);
+NAME_ARGS(gamma);
+COMPLEX_FUNCTION(set_range,float,float,float,float);
+NAME_ARGS(min_x,max_x,min_y,max_y);
+FUNCTION(get_vector, "function(int:array(float))");
+NAME_ARGS(num_points);
+{
+  int num_points, q=0;
+  gfloat *vector;
+  get_all_args("get_vector", args, "%d", &num_points);
+  pop_n_elems(args);
+  vector = malloc(sizeof(gfloat) * num_points);
+  gtk_curve_get_vector( GTK_CURVE(THIS->obj), num_points, vector );
+  while(q < num_points)
+    push_float(vector[q++]);
+  f_aggregate(num_points);
+  free(vector);
+}
+COMPLEX_FUNCTION(set_vector, floatarray);
+NAME_ARGS(curve);
+COMPLEX_FUNCTION(set_curve_type,int);
+NAME_ARGS(type);
+// One of CONST(GTK_CURVE_TYPE);
diff --git a/src/post_modules/GTK/source/gtkdata.pre b/src/post_modules/GTK/source/gtkdata.pre
new file mode 100644
index 0000000000000000000000000000000000000000..356ffb4fec9ece6c1b9f31b0995e2dffad844431
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkdata.pre
@@ -0,0 +1,4 @@
+PROGRAM(data);
+// A class inherited by all objects used to store data (they are not widgets)
+SIGNAL("disconnect", "");
+INHERIT(object);
diff --git a/src/post_modules/GTK/source/gtkdialog.pre b/src/post_modules/GTK/source/gtkdialog.pre
new file mode 100644
index 0000000000000000000000000000000000000000..4d65498d21db9fd2ef524659c74f8bb7a06d1212
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkdialog.pre
@@ -0,0 +1,11 @@
+PROGRAM(dialog);
+// A dialog is a window with a few default widgets added.
+// The 'vbox' is the main content area of the widget. The
+// 'action_area' is allocated for buttons (ok, cancel etc)
+INHERIT(window);
+COMPLEX_FUNCTION(create);
+// Create a new dialog widget.
+SUBWIDGET(vbox, vbox);
+// The vertical box that should contain the contents of the dialog
+SUBWIDGET(action_area, hbutton_box);
+// The action area, this is where the buttons (ok, cancel etc) go
diff --git a/src/post_modules/GTK/source/gtkdraw.pre b/src/post_modules/GTK/source/gtkdraw.pre
new file mode 100644
index 0000000000000000000000000000000000000000..d2e3d28d1db88b4dc79455f03af43802e04f05a1
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkdraw.pre
@@ -0,0 +1,5 @@
+PROGRAM(draw);
+INHERIT(data);
+
+#define GTK_DRAW(X) ((GtkStyle *)(X))
+/* TBD */
diff --git a/src/post_modules/GTK/source/gtkdrawingarea.pre b/src/post_modules/GTK/source/gtkdrawingarea.pre
new file mode 100644
index 0000000000000000000000000000000000000000..18f8eabae18c8b0c255b47937ce0618aef73cde7
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkdrawingarea.pre
@@ -0,0 +1,169 @@
+PROGRAM(drawing_area);
+// The drawing area is a window you can draw in.
+// Please note that you <b>must</b> handle refresh and resize events
+// on your own. Use W(pDrawingArea) for a drawingarea with automatic
+// refresh/resize handling.
+// IMG: GTK.DrawingArea()->set_usize(100,100)
+INHERIT(widget);
+COMPLEX_FUNCTION(create);
+COMPLEX_FUNCTION(size, int, int);
+NAME_ARGS(width,height);
+// The reason for this function eludes me. Use set_usize instead.
+
+
+#define TWIN GTK_WIDGET(THIS->obj)->window
+#define GC(X) ((GdkGC*)get_gdkobject(X,GC))
+FUNCTION(clear, "function(int|void,int|void,int|void,int|void:object)");
+NAME_ARGS(x,y,width,height);
+// either clears the rectangle defined by the arguments, of if no
+// arguments are specified, the whole area
+{
+  int x=0, y=0, w=0, h=0;
+  if(args==4)
+    get_all_args("clear", args, "%d%d%d%d", &x, &y, &w, &h);
+
+  if(h)
+    gdk_window_clear_area(TWIN, x,y,w,h);
+  else
+    gdk_window_clear(TWIN);
+
+  RETURN_THIS();
+}
+
+FUNCTION(draw_point, "function(object,int,int:object)");
+ARGS(GDK.GC,int,int);
+NAME_ARGS(gc,x,y);
+// gc, x, y
+// img_begin
+// w = GTK.DrawingArea()->set_usize(10,10);
+// delay: g = GDK.GC(w)->set_foreground( GDK.Color(255,0,0) );
+// delay:  for(int x = 0; x<10; x++) w->draw_point(g, x, x);
+// img_end
+{
+  struct object *g;
+  int x, y;
+  get_all_args("draw_point", args, "%o%d%d", &g, &x, &y);
+  
+  gdk_draw_point( TWIN, GC(g), x, y );
+  RETURN_THIS();
+}
+FUNCTION(draw_line, "function(object,int,int,int,int:object)");
+ARGS(GDK.GC,int,int,int,int);
+NAME_ARGS(gc,x1,y1,x2,y2);
+// img_begin
+// w = GTK.DrawingArea()->set_usize(100,100);
+// delay: g = GDK.GC(w)->set_foreground( GDK.Color(255,0,0) );
+// delay:  for(int x = 0; x<10; x++) w->draw_line(g,x*10,0,100-x*10,99);
+// img_end
+{
+  struct object *g;
+  int x, y, x2, y2;
+  get_all_args("draw_line", args, "%o%d%d%d%d", &g, &x, &y, &x2, &y2);
+  
+  gdk_draw_line( TWIN, GC(g), x, y, x2, y2 );
+  RETURN_THIS();
+}
+
+FUNCTION(draw_rectangle, "function(object,int,int,int,int,int:object)");
+ARGS(GDK.GC,int,int,int,int,int);
+NAME_ARGS(gc,filledp,x1,y1,x2,y2);
+// img_begin
+//  w = GTK.DrawingArea()->set_usize(100,100);
+// delay:  g = GDK.GC(w)->set_foreground( GDK.Color(255,0,0) );
+// delay: for(int x = 0; x<10; x++) w->draw_rectangle(g,0,x*10,0,100-x*10,99);
+// img_end
+
+// img_begin
+// w = GTK.DrawingArea()->set_usize(100,100);
+// delay:   g = GDK.GC(w);
+// delay:  for(int x = 0; x<30; x++) {
+// delay:   g->set_foreground(GDK.Color(random(255),random(255),random(255)) );
+// delay:   w->draw_rectangle(g,1,x*10,0,100-x*10,99);
+// delay: }
+// img_end
+{
+  struct object *g;
+  int f, x, y, x2, y2;
+  get_all_args("draw_rectangle",args, "%o%d%d%d%d%d",&g, &f, &x, &y, &x2, &y2);
+  gdk_draw_rectangle( TWIN, GC(g), f, x, y, x2, y2 );
+  RETURN_THIS();
+}
+
+FUNCTION(draw_arc, "function(object,int,int,int,int,int,int,int:object)");
+ARGS(GDK.GC,int,int,int,int,int,int,int);
+NAME_ARGS(gc,filledp,x1,y1,x2,y2,angle1,angle2);
+{
+  struct object *g;
+  int f, x, y, x2, y2, a1, a2;
+  get_all_args("draw_arc",args, "%o%d%d%d%d%d%d%d",&g, &f, &x, &y, &x2, &y2,
+	       &a1, &a2);
+  gdk_draw_arc( TWIN, GC(g), f, x, y, x2, y2, a1, a2 );
+  RETURN_THIS();
+}
+FUNCTION(draw_text, "function(object,object,int,int,string,int|void:object)");
+ARGS(GDK.GC,GDK.Font,int,int,string,int|void);
+NAME_ARGS(gc,font,x,y,text,forcewide);
+// y is used as the baseline for the text.
+// If forcewide is true, the string will be expanded to a wide string
+// even if it is not already one. This is useful when writing text
+// using either unicode or some other 16 bit font. 
+{
+  struct object *g,*f;
+  int x, y, force_wide=0;
+  struct pike_string *s;
+  char *swapped;
+  get_all_args("draw_text",args, "%o%o%d%d%W",&g,&f,  &x, &y, &s);
+  if( (swapped = get_swapped_string( s,args>5 )) )
+  {
+    gdk_draw_text( TWIN, get_gdkobject(f,Font),
+		   get_gdkobject(g,GC),
+		   x, y, swapped, s->len<<s->size_shift );
+    free(swapped);
+  } else {
+    gdk_draw_text( TWIN, get_gdkobject(f,Font),
+		   get_gdkobject(g,GC),
+		   x, y, s->str, s->len<<s->size_shift );
+  }
+  RETURN_THIS();
+}
+FUNCTION(draw_pixmap, "function(object,object,int,int,int,int,int,int:object)");
+ARGS(GDK.GC,GDK.Pixmap,int,int,int,int,int,int);
+NAME_ARGS(gc,pixmap,xsrc,ysrc,xdest,ydest,width,height);
+{
+  struct object *g, *p;
+  int xs, ys, xd, yd, w, h;
+  get_all_args("draw_pixmap",args,"%o%o%d%d%d%d%d%d",
+	       &g,&p,&xs,&ys,&xd,&yd,&w,&h);
+  gdk_draw_pixmap(TWIN,GC(g),get_gdkobject(p,Drawable),xs,ys,xd,yd,w,h);
+  RETURN_THIS();
+}
+
+FUNCTION(draw_bitmap, "function(object,object,int,int,int,int,int,int:object)");
+ARGS(GDK.GC,GDK.Bitmap,int,int,int,int,int,int);
+NAME_ARGS(gc,bitmap,xsrc,ysrc,xdest,ydest,width,height);
+{
+  struct object *g, *p;
+  int xs, ys, xd, yd, w, h;
+  get_all_args("draw_pixmap",args,"%o%o%d%d%d%d%d%d",
+	       &g,&p,&xs,&ys,&xd,&yd,&w,&h);
+  /* Hm. gdk_draw_bitmap does not exist? Not that it matters. */
+  gdk_draw_pixmap(TWIN,GC(g),get_gdkobject(p,Drawable),xs,ys,xd,yd,w,h);
+  RETURN_THIS();
+}
+
+FUNCTION(draw_image, "function(object,object,int,int,int,int,int,int:object)");
+ARGS(GDK.GC,GDK.Image,int,int,int,int,int,int);
+NAME_ARGS(gc,image,xsrc,ysrc,xdest,ydest,width,height);
+{
+  struct object *g, *p;
+  int xs, ys, xd, yd, w, h;
+  get_all_args("draw_pixmap",args,"%o%o%d%d%d%d%d%d",
+	       &g,&p,&xs,&ys,&xd,&yd,&w,&h);
+  gdk_draw_image(TWIN,GC(g),get_gdkobject(p,Image),xs,ys,xd,yd,w,h);
+  RETURN_THIS();
+}
+/* FUNCTION(draw_polygon, "function(object,int,array(array(int)))"); */
+/* // gc, filledp, array with xy pairs */
+/* { */
+  
+/* } */
diff --git a/src/post_modules/GTK/source/gtkeditable.pre b/src/post_modules/GTK/source/gtkeditable.pre
new file mode 100644
index 0000000000000000000000000000000000000000..0f8139a4da5cb87c997cbe25566d9b75ee0921f2
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkeditable.pre
@@ -0,0 +1,80 @@
+PROGRAM(editable);
+// The GTK.Editable class is a base class for widgets for editing text,
+// such as W(Entry) and W(Text). It cannot be instantiated by
+// itself. The editable class contains functions for generically
+// manipulating an editable widget, a large number of action signals
+// used for key bindings, and several signals that an application can
+// connect to to modify the behavior of a widget.
+SIGNAL("activate", "Indicates that the user has activated the widget in some fashion. Generally, this will be done with a keystroke. (The default binding for this action is Return for GTK.Entry and Control-Return for GTK.Text.");
+SIGNAL("changed", "Called when the text in the edit area is changed");
+SIGNAL("insert_text", "This signal is emitted when text is inserted into the widget by the user. The default handler for this signal will normally be responsible for inserting the text, so by connecting to this signal and then stopping the signal with signal_emit_stop(), it is possible to modify the inserted text, or prevent it from being inserted entirely.");
+SIGNAL("delete_text", "This signal is emitted when text is deleted from the widget by the user. The default handler for this signal will normally be responsible for inserting the text, so by connecting to this signal and then stopping the signal with signal_emit_stop(), it is possible to modify the inserted text, or prevent it from being inserted entirely. The start_pos and end_pos parameters are interpreted as for delete_text()");
+SIGNAL("set_editable", "Determines if the user can edit the text in the editable widget or not. This is meant to be overriden by child classes and should not generally be useful to applications.");
+SIGNAL("move_cursor", "An action signal. Move the cursor position.");
+SIGNAL("move_word", "An action signal. Move the cursor by words.");
+SIGNAL("move_page", "An action signal. Move the cursor by pages.");
+SIGNAL("move_to_row", "An action signal. Move the cursor to the given row.");
+SIGNAL("move_to_column", "An action signal. Move the cursor to the given column.");
+SIGNAL("kill_char", "An action signal. Delete a single character.");
+SIGNAL("kill_word", "n action signal. Delete a single word.");
+SIGNAL("kill_line", "An action signal. Delete a single line.");
+SIGNAL("cut_clipboard", "An action signal. Causes the characters in the current selection to be copied to the clipboard and then deleted from the widget.");
+SIGNAL("copy_clipboard", "An action signal. Causes the characters in the current selection to be copied to the clipboard.");
+SIGNAL("paste_clipboard", "An action signal. Causes the contents of the clipboard to be pasted into the editable widget at the current cursor position.");
+INHERIT(widget);
+COMPLEX_FUNCTION(select_region, int, int);
+NAME_ARGS(start_pos,end_pos);
+// Selects a region of text. The characters that are selected are
+// those characters at positions from start_pos up to, but not
+// including end_pos. If end_pos is negative, then the the characters
+// selected will be those characters from start_pos to the end of the
+// text. are
+COMPLEX_FUNCTION(insert_text, string, int, intp);
+NAME_ARGS(text,num_chars,where);
+// Insert 'num_chars' characters from the text at the position 'where'.
+COMPLEX_FUNCTION(delete_text, int, int);
+NAME_ARGS(start_pos,end_pos);
+// Delete a sequence of characters. The characters that are deleted
+// are those characters at positions from start_pos up to, but not
+// including end_pos. If end_pos is negative, then the the characters
+// deleted will be those characters from start_pos to the end of the
+// text.
+COMPLEX_FUNCTION(cut_clipboard);
+// Causes the characters in the current selection to be copied to the
+// clipboard and then deleted from the widget.
+COMPLEX_FUNCTION(copy_clipboard);
+// Causes the characters in the current selection to be copied to the
+// clipboard.
+COMPLEX_FUNCTION(paste_clipboard);
+// Causes the contents of the clipboard to be pasted into the given
+// widget at the current cursor position.
+COMPLEX_FUNCTION(claim_selection,int, int);
+NAME_ARGS(claimp,unix_time);
+// Claim or disclaim ownership of the PRIMARY X selection.
+string COMPLEX_FUNCTION(get_chars, int,int);
+NAME_ARGS(start_pos,end_pos);
+// Retrieves a sequence of characters. The characters that are
+// retrieved are those characters at positions from start_pos up to,
+// but not including end_pos. If end_pos is negative, then the the
+// characters retrieved will be those characters from start_pos to the
+// end of the text.
+COMPLEX_FUNCTION(set_position, int);
+NAME_ARGS(pos);
+// Sets the cursor position.
+int COMPLEX_FUNCTION(get_position);
+// Returns the cursor position
+COMPLEX_FUNCTION(set_editable, int);
+NAME_ARGS(editablep);
+// Determines if the user can edit the text in the editable widget or
+// not.
+CLASSMEMBER(selection_start_pos, int);
+// returns the cursor position of the selection start
+CLASSMEMBER(selection_end_pos, int);
+// returns the cursor position of the selection end
+CLASSMEMBER(clipboard_text, string);
+// returns the text currently in the clipboard.
+SIMPLE_FUNCTION(delete_selection);
+// Deletes the current contents of the widgets selection and disclaims
+// the selection.
+SIMPLE_FUNCTION(changed);
+// Causes the "changed" signal to be emitted.
diff --git a/src/post_modules/GTK/source/gtkentry.pre b/src/post_modules/GTK/source/gtkentry.pre
new file mode 100644
index 0000000000000000000000000000000000000000..b1cf78f6828d02ba6fbe12877dce6b4c74b298a1
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkentry.pre
@@ -0,0 +1,28 @@
+PROGRAM(entry);
+// Use this widget when you want the user to input a single line of text.
+// IMG: GTK.Entry()->set_text("Hello world")->set_editable(1)
+INHERIT(editable);
+COMPLEX_FUNCTION(create);
+COMPLEX_FUNCTION(set_text, string);
+NAME_ARGS(text);
+// Set the text to the specified string. The old text is dropped.
+COMPLEX_FUNCTION(append_text, string);
+NAME_ARGS(text);
+// Append the specified string at the end of the entry
+COMPLEX_FUNCTION(prepend_text, string);
+NAME_ARGS(text);
+// Prepend the specified string to the start of the entry
+/* COMPLEX_FUNCTION(set_position, int); */
+/* NAME_ARGS(point); */
+/* COMPLEX_FUNCTION(select_region, int,int); */
+/* NAME_ARGS(from,to); */
+COMPLEX_FUNCTION(set_visibility, int);
+NAME_ARGS(visiblep);
+// 0 indicates invisible text (password boxes, as an example)
+/* COMPLEX_FUNCTION(set_editable, int); */
+/* NAME_ARGS(editablep); */
+COMPLEX_FUNCTION(set_max_length, int);
+NAME_ARGS(maxlen);
+// text is truncated if needed
+string COMPLEX_FUNCTION(get_text);
+// Returns the contents of the entry widget.
diff --git a/src/post_modules/GTK/source/gtkeventbox.pre b/src/post_modules/GTK/source/gtkeventbox.pre
new file mode 100644
index 0000000000000000000000000000000000000000..75087d5c6f05238f5b841c49f9886a574beacfc5
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkeventbox.pre
@@ -0,0 +1,26 @@
+PROGRAM(event_box);
+// Some gtk widgets don't have associated X windows, so they just draw
+// on their parents. Because of this, they cannot recieve events and
+// if they are incorrectly sized, they don't clip so you can get messy
+// overwritting etc. If you require more from these widgets, the
+// EventBox is for you.
+//<p>
+// At first glance, the EventBox widget might appear to be totally
+// useless. It draws nothing on the screen and responds to no
+// events. However, it does serve a function - it provides an X window
+// for its child widget. This is important as many GTK widgets do not
+// have an associated X window. Not having an X window saves memory
+// and improves performance, but also has some drawbacks. A widget
+// without an X window cannot receive events, and does not perform any
+// clipping on it's contents. Although the name EventBox emphasizes
+// the event-handling function, the widget can also be used for
+// clipping.
+//<p>
+// The primary use for this widget is when you want to receive events
+// for a widget without a window. Examples of such widgets are labels
+// and images.
+//
+// IMG: GTK.EventBox()->set_usize(100,100)
+INHERIT(bin);
+COMPLEX_FUNCTION(create);
+// Create a new event box widget
diff --git a/src/post_modules/GTK/source/gtkfileselection.pre b/src/post_modules/GTK/source/gtkfileselection.pre
new file mode 100644
index 0000000000000000000000000000000000000000..05470acc254bc253fc8a9aea61988c00dd8e706b
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkfileselection.pre
@@ -0,0 +1,80 @@
+PROGRAM(file_selection);
+
+
+// GtkFileSelection should be used to retrieve file or directory names
+// from the user. It will create a new dialog window containing a
+// directory list, and a file list corresponding to the current
+// working directory. The filesystem can be navigated using the
+// directory list, the drop-down history menu, or the TAB key can be
+// used to navigate using filename completion common in text based
+// editors such as emacs and jed.
+
+// <p>
+
+// The default filename can be set using set_filename() and the
+// selected filename retrieved using get_filename().
+
+// <p>
+
+// Use complete() to display files that match a given pattern. This
+// can be used for example, to show only *.txt files, or only files
+// beginning with gtk*.
+
+// <p> 
+
+// Simple file operations; create directory, delete file, and rename
+// file, are available from buttons at the top of the dialog. These
+// can be hidden using hide_fileop_buttons() and shown again using
+// show_fileop_buttons().
+
+// <p>
+
+// TIMG: GTK.FileSelection("File selector")
+INHERIT(window);
+SUBWIDGET(ok_button, button);
+// The ok button
+SUBWIDGET(cancel_button, button);
+// The cancel button
+SUBWIDGET(help_button, button);
+// The help button
+SUBWIDGET(fileop_c_dir, button);
+// The create directory button in the file operation button group
+SUBWIDGET(fileop_del_file, button);
+// The delete file button in the file operation button group
+SUBWIDGET(fileop_ren_file, button);
+// The rename file button in the file operation button group
+SUBWIDGET(dir_list, clist);
+// The list of directories
+SUBWIDGET(file_list, clist);
+// The list of files
+SUBWIDGET(history_pulldown, option_menu);
+// Used to create the drop-down directory histor
+
+string COMPLEX_FUNCTION(get_filename);
+// Returns the currently entered filename as a string
+COMPLEX_FUNCTION(create, string);
+NAME_ARGS(window_title);
+// Creates a new file selection dialog box. By default it will list
+// the files in the current working directory. Operation buttons
+// allowing the user to create a directory, delete files, and rename
+// files will also be present by default.
+COMPLEX_FUNCTION(set_filename, string);
+NAME_ARGS(fname);
+// Sets a default path for the file requestor. If filename includes a
+// directory path, then the requestor will open with that path as its
+// current working directory.
+SIMPLE_FUNCTION(show_fileop_buttons);
+// Shows the file operation buttons, if they have previously been
+// hidden. The rest of the widgets in the dialog will be resized
+// accordingly.
+SIMPLE_FUNCTION(hide_fileop_buttons);
+// Hides the file operation buttons that normally appear at the top of
+// the dialog. Useful if you wish to create a custom file selector,
+// based on GTK.FileSelection.
+COMPLEX_FUNCTION(complete, string);
+NAME_ARGS(pattern);
+// Will attempt to match pattern to a valid filename in the current
+// directory. If a match can be made, the matched filename will appear
+// in the text entry field of the file selection dialog. If a partial
+// match can be made, the "Files" list will contain those file names
+// which have been partially matched.
diff --git a/src/post_modules/GTK/source/gtkfixed.pre b/src/post_modules/GTK/source/gtkfixed.pre
new file mode 100644
index 0000000000000000000000000000000000000000..0de49557d01bd5a4f7603804343fa34d8713f965
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkfixed.pre
@@ -0,0 +1,15 @@
+PROGRAM(fixed);
+// A fixed container is a container that keeps it's children at fixed
+// locations and give them fixed sizes, both given in pixels.
+// <p>
+//  Example:
+// IMG: GTK.Fixed()->put(GTK.Label("100,100"), 100, 100)->put(GTK.Label("0,0"), 0, 0)->set_usize(150,115)
+INHERIT(container);
+COMPLEX_FUNCTION(create);
+// Create a new fixed widget
+COMPLEX_FUNCTION(put,widget,int,int);
+NAME_ARGS(widget,x,y);
+// Place the widget at xpos,ypos.
+COMPLEX_FUNCTION(move,widget,int,int);
+NAME_ARGS(widget,new_xpos,new_ypos);
+// Move the widget to new_xpos,new_ypos from it's old location.
diff --git a/src/post_modules/GTK/source/gtkfontselection.pre b/src/post_modules/GTK/source/gtkfontselection.pre
new file mode 100644
index 0000000000000000000000000000000000000000..a501129e287486f96b584dda06615234cef34751
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkfontselection.pre
@@ -0,0 +1,38 @@
+PROGRAM(font_selection);
+// IMG: GTK.FontSelection()
+INHERIT(notebook);
+
+SUBWIDGET(main_vbox, vbox);
+SUBWIDGET(font_label, label);
+SUBWIDGET(font_entry, entry);
+SUBWIDGET(font_clist, clist);
+SUBWIDGET(font_style_entry, entry);
+SUBWIDGET(font_style_clist, clist);
+SUBWIDGET(size_entry, entry);
+SUBWIDGET(size_clist, clist);
+SUBWIDGET(pixels_button, button);
+SUBWIDGET(points_button, button);
+SUBWIDGET(filter_button, button);
+SUBWIDGET(preview_entry, entry);
+SUBWIDGET(message_label, label);
+
+SUBWIDGET(info_vbox, vbox);
+SUBWIDGET(info_clist, clist);
+SUBWIDGET(requested_font_name, label);
+SUBWIDGET(actual_font_name, label);
+
+SUBWIDGET(filter_vbox, vbox);
+SUBWIDGET(type_bitmaps_button, button);
+SUBWIDGET(type_scalable_button, button);
+SUBWIDGET(type_scaled_bitmaps_button, button);
+GDK.Font COMPLEX_FUNCTION(get_font);
+string COMPLEX_FUNCTION(get_font_name);
+COMPLEX_FUNCTION(set_font_name, string);
+NAME_ARGS(xlfd);
+// This sets the currently displayed font. It should be a valid X Logical
+// Font Description font name (anything else will be ignored), e.g.
+// "-adobe-courier-bold-o-normal--25-*-*-*-*-*-*-*" 
+COMPLEX_FUNCTION(create);
+string COMPLEX_FUNCTION(get_preview_text);
+COMPLEX_FUNCTION(set_preview_text, string);
+NAME_ARGS(text);
diff --git a/src/post_modules/GTK/source/gtkfontselectiondialog.pre b/src/post_modules/GTK/source/gtkfontselectiondialog.pre
new file mode 100644
index 0000000000000000000000000000000000000000..6076fdb5d170f80e7783e0b90ffd7d78e4abe582
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkfontselectiondialog.pre
@@ -0,0 +1,34 @@
+PROGRAM(font_selection_dialog);
+// The GtkFontSelectionDialog widget is a dialog box for selecting a font.
+// <p>
+// To set the font which is initially selected, use set_font_name().
+// <p>
+// To get the selected font use get_font() or get_font_name().
+// <p>
+// To change the text which is shown in the preview area, use
+// set_preview_text().
+// <p>
+// The base filter is not yet implemented in Pike GTK.
+// <p><i><font size=-1>
+// Filters can be used to limit the fonts shown. There are 2 filters in
+// the GtkFontSelectionDialog - a base filter and a user filter. The
+// base filter can not be changed by the user, so this can be used when
+// the user must choose from the restricted set of fonts (e.g. for a
+// terminal-type application you may want to force the user to select a
+// fixed-width font). The user filter can be changed or reset by the
+// user, by using the 'Reset Filter' button or changing the options on
+// the 'Filter' page of the dialog.
+// <font size=-1></i>
+// TIMG: GTK.FontSelectionDialog("Select a font")
+INHERIT(window);
+SUBWIDGET(fontsel, font_selection);
+// The W(FontSelection) widget
+SUBWIDGET(ok_button, button);
+// The ok button
+SUBWIDGET(apply_button, button);
+// The apply button
+SUBWIDGET(cancel_button, button);
+// The cancel button
+COMPLEX_FUNCTION(create, string);
+NAME_ARGS(title);
+// Create a new font selection dialog with the specified window title
diff --git a/src/post_modules/GTK/source/gtkframe.pre b/src/post_modules/GTK/source/gtkframe.pre
new file mode 100644
index 0000000000000000000000000000000000000000..10fbef138c233d76abf2cb4ce5d99d47fd2b3d5f
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkframe.pre
@@ -0,0 +1,48 @@
+/* -*- c -*- */
+
+PROGRAM(frame);
+
+
+// The frame widget is a Bin that surrounds its child with a
+// decorative frame and an optional label. If present, the label is
+// drawn in a gap in the top side of the frame. The position of the
+// label can be controlled with set_label_align().
+// <p>
+// Used to visually group objects.
+// <p>
+// IMG: GTK.Frame("Title")->add(GTK.Label("Contents"))
+// IMG: GTK.Frame()->add(GTK.Label("Contents"))
+// IMG: GTK.Frame()->add(GTK.Label("Contents"))->set_shadow_type(GTK.SHADOW_IN)
+INHERIT(container);
+FUNCTION(create, "function(string|void:void)")
+NAME_ARGS(label_text);
+// Create a new Frame, with optional label label_text. If no label is
+// specified, the label is omitted, and there will be no gap in the
+// frame.
+{
+  char *title = NULL;
+  if(args)
+  {
+    if((sp[-1].type == T_STRING) && sp[-1].u.string->len)
+      title = sp[-1].u.string->str;
+  }
+  if(THIS->obj) error("GTK.Frame->create() can only be called once.\n");
+  THIS->obj = GTK_OBJECT( gtk_frame_new( title ) );
+  pgtk__init_this_object();
+}
+
+COMPLEX_FUNCTION(set_label, string);
+NAME_ARGS(label_text);
+// Set the text of the label.
+
+COMPLEX_FUNCTION(set_label_align, float, float);
+NAME_ARGS(xalign,yalign);
+// Arguments are xalignment and yalignment.
+// 0.0 is left or topmost, 1.0 is right or bottommost.<br>
+// The default value for a newly created Frame is 0.0.
+
+COMPLEX_FUNCTION(set_shadow_type,int);
+NAME_ARGS(shadow_type);
+// Set the shadow type for the Frame widget. The type is one of
+// CONST(GTK_SHADOW)
+
diff --git a/src/post_modules/GTK/source/gtkgammacurve.pre b/src/post_modules/GTK/source/gtkgammacurve.pre
new file mode 100644
index 0000000000000000000000000000000000000000..65f83883819f268a718d0db9719d5d9665fd7e0a
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkgammacurve.pre
@@ -0,0 +1,18 @@
+PROGRAM(gamma_curve);
+// A gamma curve widget.. Rather complex.
+// <p>
+// Lets the user edit a gamma curve (a one-to-one mapping usually used
+// to adjust the intensity of an image to the physical characteristics
+// of the output device). You can set the minimum and maximum values
+// for input and output. You can set the initial vector as well. You
+// are guaranteed that every input value will have a (not necessarily
+// unique) output value specified.
+//
+// IMG: GTK.GammaCurve()->set_usize(210,130)
+INHERIT(vbox);
+COMPLEX_FUNCTION(create);
+// Create a new gamma curve
+SUBWIDGET(curve, curve);
+// The actual curve
+CLASSMEMBER(gamma, float);
+// The current gamma value
diff --git a/src/post_modules/GTK/source/gtkglarea.pre b/src/post_modules/GTK/source/gtkglarea.pre
new file mode 100644
index 0000000000000000000000000000000000000000..dd04d0e52da99826f3d6bd386f131ec17a53c808
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkglarea.pre
@@ -0,0 +1,72 @@
+COND_WIDGET(glarea);
+PROGRAM(gl_area);
+INHERIT(drawing_area);
+
+
+ADD_INCLUDE(#include <gtkgl/gdkgl.h>);
+ADD_INCLUDE(#include <gtkgl/gtkglarea.h>);
+
+#include <gtkgl/gdkgl.h>
+#include <gtkgl/gtkglarea.h>
+
+
+COMPLEX_FUNCTION(create, intarray);
+NAME_ARGS(gloptions);
+
+COMPLEX_FUNCTION(make_current);
+
+FUNCTION(swap_buffers, "function(void:object)");
+{
+  gdk_gl_swap_buffers( GTK_WIDGET(THIS->obj)->window );
+  RETURN_THIS();
+}
+
+
+FUNCTION(wait_gl, "function(void:object)");
+{
+  gdk_gl_wait_gl();
+  RETURN_THIS();
+}
+
+FUNCTION(wait_gdk, "function(void:object)");
+{
+  gdk_gl_wait_gdk();
+  RETURN_THIS();
+}
+
+/* FUNCTION(use_gdk_font, "function(object, int, int, int )"); */
+/* { */
+/*   struct object *o; */
+/*   int first, count, list_base; */
+/*   get_all_args( "use_gdk_font", args, "%o%d%d%d",  */
+/*                 &o, &first, &count, &list_base); */
+/*   gdk_gl_use_gdk_font(get_gdkobjectclass( o, Font ),first,count,list_base); */
+/* } */
+
+CONSTANT(GDK_GL_NONE);
+CONSTANT(GDK_GL_USE_GL);
+CONSTANT(GDK_GL_BUFFER_SIZE);
+CONSTANT(GDK_GL_LEVEL);
+CONSTANT(GDK_GL_RGBA);
+CONSTANT(GDK_GL_DOUBLEBUFFER);
+CONSTANT(GDK_GL_STEREO);
+CONSTANT(GDK_GL_AUX_BUFFERS);
+CONSTANT(GDK_GL_RED_SIZE);
+CONSTANT(GDK_GL_GREEN_SIZE);
+CONSTANT(GDK_GL_BLUE_SIZE);
+CONSTANT(GDK_GL_ALPHA_SIZE);
+CONSTANT(GDK_GL_DEPTH_SIZE);
+CONSTANT(GDK_GL_STENCIL_SIZE);
+CONSTANT(GDK_GL_ACCUM_RED_SIZE);
+CONSTANT(GDK_GL_ACCUM_GREEN_SIZE);
+CONSTANT(GDK_GL_ACCUM_BLUE_SIZE);
+CONSTANT(GDK_GL_ACCUM_ALPHA_SIZE);
+CONSTANT(GDK_GL_X_VISUAL_TYPE_EXT);
+CONSTANT(GDK_GL_TRANSPARENT_TYPE_EXT);
+CONSTANT(GDK_GL_TRANSPARENT_INDEX_VALUE_EXT);
+CONSTANT(GDK_GL_TRANSPARENT_RED_VALUE_EXT);
+CONSTANT(GDK_GL_TRANSPARENT_GREEN_VALUE_EXT);
+CONSTANT(GDK_GL_TRANSPARENT_BLUE_VALUE_EXT);
+CONSTANT(GDK_GL_TRANSPARENT_ALPHA_VALUE_EXT);
+
+END_COND_WIDGET(glarea);
diff --git a/src/post_modules/GTK/source/gtkhandlebox.pre b/src/post_modules/GTK/source/gtkhandlebox.pre
new file mode 100644
index 0000000000000000000000000000000000000000..4d1067fa8adba952bd466dff89398e3255af70fa
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkhandlebox.pre
@@ -0,0 +1,37 @@
+PROGRAM(handle_box);
+// The contents of a handle box can be 'dragged' out of the box by the user.
+// The contents will then be placed in a separate window.
+// IMG: GTK.HandleBox()->add(GTK.Label("The contents")) 
+SIGNAL("child_attached", "Called when a new child is added to the box");
+SIGNAL("child_detached", "Called when a child is removed from the box");
+INHERIT(bin);
+COMPLEX_FUNCTION(create);
+// Create a new handle box widget.
+COMPLEX_FUNCTION(set_shadow_type, int);
+NAME_ARGS(shadow_type);
+// One of CONST(GTK_SHADOW)
+
+COMPLEX_FUNCTION(set_handle_position, int);
+NAME_ARGS(pos);
+// The position of the handle. One of CONST(GTK_POS_)
+
+COMPLEX_FUNCTION(set_snap_edge, int);
+NAME_ARGS(pos);
+// The edge to snap to. One of CONST(GTK_POS_), or -1 for unset.
+
+
+CLASSMEMBER(snap_edge, int);
+// The edge to snap to. One of CONST(GTK_POS_), or -1 for unset.
+CLASSMEMBER(in_drag, int);
+// 1 if the window is beeing dragged around right now.
+CLASSMEMBER(shrink_on_detach, int);
+// True if the container should shrink when the child is detatched
+SETCLASSMEMBER(shrink_on_detach, int);
+NAME_ARGS(shrinkp);
+// True if the container should shrink when the child is detatched
+CLASSMEMBER(child_detached, int);
+// Is the child detatched?
+CLASSMEMBER(float_window_mapped, int);
+// Is the floating window mapped?
+CLASSMEMBER(handle_position, int);
+// The position of the handle. One of CONST(GTK_POS_)
diff --git a/src/post_modules/GTK/source/gtkhbbox.pre b/src/post_modules/GTK/source/gtkhbbox.pre
new file mode 100644
index 0000000000000000000000000000000000000000..9a326a21b9051d0d037f6a26df8575208a795ae0
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkhbbox.pre
@@ -0,0 +1,14 @@
+PROGRAM(hbutton_box);
+// A HbuttonBox is very similar to a Hbox.
+// The major diffference is that the button box
+// is made to pack buttons in, and has a few convenience function for 
+// normal button layouts.
+// 
+// IMG: GTK.HbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_usize(400,30)
+// IMG: GTK.HbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_layout(GTK.BUTTONBOX_SPREAD)->set_usize(400,30)
+// IMG: GTK.HbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_layout(GTK.BUTTONBOX_EDGE)->set_usize(400,30)
+// IMG: GTK.HbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_layout(GTK.BUTTONBOX_START)->set_usize(400,30)
+// IMG: GTK.HbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_layout(GTK.BUTTONBOX_END)->set_usize(400,30)
+INHERIT(button_box);
+COMPLEX_FUNCTION(create);
+// Create a new horizontal button box
diff --git a/src/post_modules/GTK/source/gtkhbox.pre b/src/post_modules/GTK/source/gtkhbox.pre
new file mode 100644
index 0000000000000000000000000000000000000000..96c0b6de8f464c6cfa8d7e105c62fb6d582c9ff4
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkhbox.pre
@@ -0,0 +1,17 @@
+PROGRAM(hbox);
+// Most packing is done by creating boxes. These are invisible widget
+// containers that we can pack our widgets into which come in two
+// forms, a horizontal box, and a vertical box. This is the horizontal
+// one.  When packing widgets into a horizontal box, the objects are
+// inserted horizontally from left to right or right to left depending
+// on the call used.
+//
+// IMG: GTK.Hbox(0,0)->add(GTK.Button("Hello"))->add(GTK.Button("World"))->pack_end_defaults(GTK.Button("From right"))->pack_start_defaults(GTK.Button("From left"))
+// IMG: GTK.Hbox(1,0)->add(GTK.Button("Hello"))->add(GTK.Button("World"))->pack_end_defaults(GTK.Button("From right"))->pack_start_defaults(GTK.Button("From left"))
+// IMG: GTK.Hbox(1,40)->add(GTK.Button("Hello"))->add(GTK.Button("World"))->pack_end_defaults(GTK.Button("From right"))->pack_start_defaults(GTK.Button("From left"))
+INHERIT(box);
+COMPLEX_FUNCTION(create, int, int);
+NAME_ARGS(all_same_size, hpadding);
+// Create a new horizontal box widget.
+// If all_same_size is true, all widgets will have exactly the same size.
+// hpadding is added to the left and right of the children.
diff --git a/src/post_modules/GTK/source/gtkhpaned.pre b/src/post_modules/GTK/source/gtkhpaned.pre
new file mode 100644
index 0000000000000000000000000000000000000000..e64b5584ac7d6bf87417f7c2bec3abe6695c58ab
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkhpaned.pre
@@ -0,0 +1,12 @@
+PROGRAM(hpaned);
+// The paned window widgets are useful when you want to divide an area
+// into two parts, with the relative size of the two parts controlled
+// by the user. A groove is drawn between the two portions with a
+// handle that the user can drag to change the ratio. This widgets
+// makes a horizontal division
+// <p>
+// See W(Paned) for details.
+// <p>
+// IMG: GTK.Hpaned()->add1(GTK.Label("Left\nSide\nOf\nPane"))->add2(GTK.Label("Right\nSide\nOf\nPane"))->set_usize(100,100)
+INHERIT(paned);
+COMPLEX_FUNCTION(create);
diff --git a/src/post_modules/GTK/source/gtkhruler.pre b/src/post_modules/GTK/source/gtkhruler.pre
new file mode 100644
index 0000000000000000000000000000000000000000..bdc5f458c90bcf414cc879e7af1a1075123ef90f
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkhruler.pre
@@ -0,0 +1,13 @@
+PROGRAM(hruler);
+// Ruler widgets are used to indicate the location of the mouse
+// pointer in a given window. A window can have a vertical ruler
+// spanning across the width and a horizontal ruler spanning down the
+// height. A small triangular indicator on the ruler shows the exact
+// location of the pointer relative to the ruler.
+//
+// IMG: GTK.Hruler()->set_metric(GTK.PIXELS)->set_range(0.0,100.0,50.0,100.0)->draw_ticks()->draw_pos()->set_usize(300,30)
+// IMG: GTK.Hruler()->set_metric(GTK.CENTIMETERS)->set_range(0.0,100.0,50.0,100.0)->draw_ticks()->draw_pos()->set_usize(300,30)
+// IMG: GTK.Hruler()->set_usize(300,30)
+INHERIT(ruler);
+COMPLEX_FUNCTION(create);
+// Used to create a new hruler widget.
diff --git a/src/post_modules/GTK/source/gtkhscale.pre b/src/post_modules/GTK/source/gtkhscale.pre
new file mode 100644
index 0000000000000000000000000000000000000000..710a3bdb1eaa8c70a773cc2d6b1e50406741d9c8
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkhscale.pre
@@ -0,0 +1,22 @@
+PROGRAM(hscale);
+// The GTK.HScale widget is used to allow the user to select a value
+// using a horizontal slider. A GTK.Adjustment is used to set the
+// initial value, the lower and upper bounds, and the step and page
+// increments.
+// <p>
+// See W(Scale) for details
+// <p>
+// The position to show the current value, and the number of decimal
+// places shown can be set using the parent W(Scale) class's
+// functions.
+// IMG: GTK.Hscale(GTK.Adjustment())->set_usize(300,30)
+INHERIT(scale);
+COMPLEX_FUNCTION(create, ?adjustment);
+NAME_ARGS(settings);
+// Used to create a new hscale widget.
+// The adjustment argument can either be an existing W(Adjustment), or
+// 0, in which case one will be created for you. Specifying 0 might
+// actually be useful in this case, if you wish to pass the newly
+// automatically created adjustment to the constructor function of
+// some other widget which will configure it for you, such as a text
+// widget.
diff --git a/src/post_modules/GTK/source/gtkhscrollbar.pre b/src/post_modules/GTK/source/gtkhscrollbar.pre
new file mode 100644
index 0000000000000000000000000000000000000000..683156e8f546ea16ee474ed6e30dd464ce015953
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkhscrollbar.pre
@@ -0,0 +1,15 @@
+PROGRAM(hscrollbar);
+// A horizontal scrollbar.<p>
+// General documentation: See W(Scrollbar)
+// IMG: GTK.Hscrollbar(GTK.Adjustment())->set_usize(300,15)
+//
+INHERIT(scrollbar);
+COMPLEX_FUNCTION(create, ?adjustment);
+NAME_ARGS(adjustment);
+// Used to create a new vscale widget.
+// The adjustment argument can either be an existing W(Adjustment), or
+// 0, in which case one will be created for you. Specifying 0 might
+// actually be useful in this case, if you wish to pass the newly
+// automatically created adjustment to the constructor function of
+// some other widget which will configure it for you, such as a text
+// widget.
diff --git a/src/post_modules/GTK/source/gtkhseparator.pre b/src/post_modules/GTK/source/gtkhseparator.pre
new file mode 100644
index 0000000000000000000000000000000000000000..2806df73f04d6b271b26e8879768036820e13523
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkhseparator.pre
@@ -0,0 +1,6 @@
+PROGRAM(hseparator);
+// Simply creates a horizontal separator. No bells or whistles.
+// IMG: GTK.Hseparator()->set_usize(300,3)
+INHERIT(separator);
+COMPLEX_FUNCTION(create);
+// Used to create a new hseparator widget.
diff --git a/src/post_modules/GTK/source/gtkimage.pre b/src/post_modules/GTK/source/gtkimage.pre
new file mode 100644
index 0000000000000000000000000000000000000000..8538b51e98cc3f1c44e40cba752f682a863d7edd
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkimage.pre
@@ -0,0 +1,93 @@
+PROGRAM(image);
+// An image is a image object stored in client, not X server, memory.
+// A pixmap, on the other hand, is a image object stored in the X-server.
+// See GDK.Image and GDK.Pixmap.
+//<p>
+// IMG: GTK.Image( GDK.Image(0)->set(Image.image(200,200)->test() ) );
+INHERIT(misc);
+FUNCTION(create, "function(object,object|void:void)");
+ARGS(GDK.Image,GDK.Bitmap|void);
+NAME_ARGS(image,mask);
+// You can skip the mask. The mask is used to mask the drawing of the image
+// on it's background. It will not make the container transparent, though.
+// Use shape_combine_mask on the container with the mask for that.
+{
+  struct object *a, *b;
+  GdkImage *img;
+  GdkBitmap *mask = NULL;
+  if(THIS->obj) error("GTK.Image->create() can only be called once.\n");
+  if(args == 2)
+    get_all_args("GDK.Image", args, "%o%o", &a, &b);
+  else
+  {
+    get_all_args("GDK.Image", args, "%o", &a);
+    b = 0;
+  }
+ add_ref(a);
+  img = get_gdkobject( a,Image );
+  if(b)
+  {
+    mask = get_gdkobject( b,Bitmap );
+ add_ref(b);
+  }
+  THIS->obj = GTK_OBJECT( gtk_image_new( img, mask ) );
+  pgtk__init_this_object();
+  pop_n_elems(args);
+}
+
+FUNCTION(set, "function(object,object|void:object)")
+ARGS(GDK.Image,GDK.Bitmap|void);
+NAME_ARGS(image,mask);
+RETURNS(GTK.Image);
+// Args: GDK.Image and GDK.Bitmap, respectively.
+// You can skip the mask. The mask is used to mask the drawing of the image
+// on it's background. It will not make the container transparent, though.
+// Use shape_combine_mask on the container with the mask for that.
+// <p>
+// There is no need to call 'set' with the same GDK.Image again if
+// you have modified the image. You must, however, use -&gt;queue_draw()
+// to redraw the image. Otherwise the old contens would be show until
+// it an refresh is done for any other reason.
+{
+  struct object *a, *b;
+  GdkImage *img;
+  GdkBitmap *mask = NULL;
+  if(args == 2)
+    get_all_args("GDK.Image", args, "%o%o", &a, &b);
+  else
+  {
+    get_all_args("GDK.Image", args, "%o", &a);
+    b = 0;
+  }
+  
+  img = get_gdkobject( a,Image );
+  if(mask)
+    mask = get_gdkobject( a,Bitmap );
+  gtk_image_set( GTK_IMAGE( THIS->obj ), img, mask );
+  RETURN_THIS();
+}
+
+FUNCTION(get, "function(void:mapping)");
+// returns ([ "image":GDK.Image img, "mask":GDK.Bitmap m ])
+{
+  GdkImage *v;
+  GdkBitmap *m;
+  pop_n_elems(args);
+  gtk_image_get( GTK_IMAGE( THIS->obj ), &v, &m );
+  push_text( "image" );
+  if(v)
+  {
+    push_gdkobject( v, Image );
+/*     gdk_image_ref( v );  we cannot do this.. */
+  }
+  else
+    push_int(0);
+  push_text( "mask" );
+  if(m)
+  {
+    push_gdkobject( m, Bitmap );
+    gdk_bitmap_ref( m );
+  }
+  else
+    push_int(0);
+}
diff --git a/src/post_modules/GTK/source/gtkinputdialog.pre b/src/post_modules/GTK/source/gtkinputdialog.pre
new file mode 100644
index 0000000000000000000000000000000000000000..25ccc7167eb6df45ea567464a8db7d2fe5d9e4f7
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkinputdialog.pre
@@ -0,0 +1,33 @@
+PROGRAM(input_dialog);
+// This dialog is used to enable XInput devices.  By default, no
+// extension devices are enabled. We need a mechanism to allow users
+// to enable and configure their extension devices. GTK provides the
+// InputDialog widget to automate this process. The following
+// procedure manages an InputDialog widget. It creates the dialog if
+// it isn't present, and shows it otherwise.
+// <p>
+// <pre><font size=-1>
+// GTK.InputDialog inputd;
+// void&nbsp;create_input_dialog&nbsp;()
+// {
+// &nbsp;&nbsp;if&nbsp;(!inputd)
+// &nbsp;&nbsp;{
+// &nbsp;&nbsp;&nbsp;&nbsp;inputd&nbsp;=&nbsp;GTK.InputDialog();
+// &nbsp;&nbsp;&nbsp;&nbsp;inputd-&gt;close_button()-&gt;signal_connect("clicked",inputd-&gt;hide,&nbsp;0);
+// &nbsp;&nbsp;&nbsp;&nbsp;inputd-&gt;save_button()-&gt;hide();
+// &nbsp;&nbsp;&nbsp;&nbsp;inputd-&gt;show();
+// &nbsp;&nbsp;}
+// &nbsp;&nbsp;else
+// &nbsp;&nbsp;&nbsp;&nbsp;inputd-&gt;show();
+// }
+// </font></pre>
+// TIMG: GTK.InputDialog()
+SIGNAL("enable_device", "This signal is emitted when the user changes the mode of a device from GDK_MODE_DISABLED to a GDK_MODE_SCREEN or GDK_MODE_WINDOW.");
+SIGNAL("disable_device", "his signal is emitted when the user changes the mode of a device from a GDK_MODE_SCREEN or GDK_MODE_WINDOW to GDK_MODE_ENABLED");
+INHERIT(dialog);
+COMPLEX_FUNCTION(create);
+// Create a new input dialog window.
+SUBWIDGET(close_button, button);
+// The 'close' button of the dialog.
+SUBWIDGET(save_button, button);
+// The 'save' button of the dialog.
diff --git a/src/post_modules/GTK/source/gtkinvisible.pre b/src/post_modules/GTK/source/gtkinvisible.pre
new file mode 100644
index 0000000000000000000000000000000000000000..8ca9d233c8a749f2c56765179e8be88b8f76bdc3
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkinvisible.pre
@@ -0,0 +1,6 @@
+PROGRAM(invisible);
+// An invisible container, useful, eh? :)
+#include <gtk/gtkinvisible.h>
+INHERIT(bin);
+COMPLEX_FUNCTION(create);
+// Create a new invisible widget
diff --git a/src/post_modules/GTK/source/gtkitem.pre b/src/post_modules/GTK/source/gtkitem.pre
new file mode 100644
index 0000000000000000000000000000000000000000..099438d29d7d62850050e7bdaba4d75b1a1a786b
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkitem.pre
@@ -0,0 +1,12 @@
+PROGRAM(item);
+// This class is inherited by all 'item' type of widgets.
+SIGNAL("select", "");
+SIGNAL("delselect", "");
+SIGNAL("toggle", "");
+INHERIT(bin);
+SIMPLE_FUNCTION(select);
+// Emulate a 'select' event.
+SIMPLE_FUNCTION(deselect);
+// Emulate a 'deselect' event.
+SIMPLE_FUNCTION(toggle);
+// Emulate a 'toggle' event.
diff --git a/src/post_modules/GTK/source/gtklabel.pre b/src/post_modules/GTK/source/gtklabel.pre
new file mode 100644
index 0000000000000000000000000000000000000000..8f7121750b92931ba31bb23f4f7f0c7f6ab02952
--- /dev/null
+++ b/src/post_modules/GTK/source/gtklabel.pre
@@ -0,0 +1,40 @@
+PROGRAM(label);
+// A simple text label.
+// IMG: GTK.Label("A simple text label")
+// IMG: GTK.Label("Multi\nline text\nlabel here")
+// IMG: GTK.Label("Multi\nline text\nlabel here")->set_justify(GTK.JUSTIFY_LEFT)
+// IMG: GTK.Label("Multi\nline text\nlabel here")->set_justify(GTK.JUSTIFY_RIGHT)
+INHERIT(misc);
+COMPLEX_FUNCTION(create, string);
+NAME_ARGS(text);
+// Creates a new label.
+COMPLEX_FUNCTION(set_text, string);
+NAME_ARGS(text);
+// Set the text in the label
+#ifndef gtk_label_set
+# define gtk_label_set gtk_label_set_text
+#endif
+COMPLEX_FUNCTION(set, string);
+NAME_ARGS(text);
+// <b>DEPRECATED</b> Compatibility function to set the text in the label. Use
+// set_text. This function can dissapear in the future.
+COMPLEX_FUNCTION(set_justify, int);
+NAME_ARGS(justify);
+// one of CONST(GTK_JUSTIFY)
+COMPLEX_FUNCTION(set_line_wrap, int);
+NAME_ARGS(wrapp);
+// Should the label autolinewrap?
+
+COMPLEX_FUNCTION(set_pattern, string);
+NAME_ARGS(pattern_string);
+// A string with either spaces or underscores.<br>
+// It should be of the same length as the text.
+// <p>
+// When a character in the text has a matching _ in the pattern, the
+// character in the label will be underlined.
+// <p>
+int COMPLEX_FUNCTION(parse_uline, string);
+NAME_ARGS(uline_string);
+// Convenience function to set the text and pattern by parsing
+// a string with embedded underscores, returns the appropriate
+// key symbol for the accelerator.
diff --git a/src/post_modules/GTK/source/gtklayout.pre b/src/post_modules/GTK/source/gtklayout.pre
new file mode 100644
index 0000000000000000000000000000000000000000..7495e080500d47f704da444ce9ca5c8c4d9b09e2
--- /dev/null
+++ b/src/post_modules/GTK/source/gtklayout.pre
@@ -0,0 +1,29 @@
+PROGRAM(layout);
+// Similar to the tcl/tk packing method.
+INHERIT(container);
+COMPLEX_FUNCTION(create, adjustment, adjustment);
+NAME_ARGS(hadjustment,vadjustment);
+COMPLEX_FUNCTION(put, widget, int, int);
+NAME_ARGS(widget, x, y);
+
+COMPLEX_FUNCTION(move, widget, int, int);
+NAME_ARGS(widget, x, y);
+
+COMPLEX_FUNCTION(set_size, int, int);
+NAME_ARGS(xsize, ysize);
+
+SIMPLE_FUNCTION(freeze);
+SIMPLE_FUNCTION(thaw);
+
+adjustment COMPLEX_FUNCTION(get_hadjustment);
+adjustment COMPLEX_FUNCTION(get_vadjustment);
+COMPLEX_FUNCTION(set_hadjustment, adjustment);
+NAME_ARGS(adj);
+COMPLEX_FUNCTION(set_vadjustment, adjustment);
+NAME_ARGS(adj);
+
+CLASSMEMBER( width, int );
+CLASSMEMBER( height, int );
+
+CLASSMEMBER( xoffset, int );
+CLASSMEMBER( yoffset, int );
diff --git a/src/post_modules/GTK/source/gtklist.pre b/src/post_modules/GTK/source/gtklist.pre
new file mode 100644
index 0000000000000000000000000000000000000000..37bce8affb6066a518b76c9eab3962404016acdc
--- /dev/null
+++ b/src/post_modules/GTK/source/gtklist.pre
@@ -0,0 +1,147 @@
+PROGRAM(list);
+// This class is not yet finished enough to be usable.
+SIGNAL("selection_changed", "...");
+SIGNAL("select_child", "...");
+SIGNAL("unselect_child", "...");
+INHERIT(container);
+COMPLEX_FUNCTION(create);
+FUNCTION(selection, "function(void:array(object))");
+RETURNS(array(GTK.Widget));
+{
+  GList *s = GTK_LIST( THIS->obj )->selection;
+  int j = 0;
+  pop_n_elems(args);
+  while( s )
+  {
+    push_gtkobjectclass( (void *)s->data, pgtk_list_item_program );
+    j++;
+    s = s->next;
+  }
+  f_aggregate( j );
+}
+
+int COMPLEX_FUNCTION(child_position, widget);
+NAME_ARGS(child);
+COMPLEX_FUNCTION(extend_selection, int,float,int);
+NAME_ARGS(scroll_type, position, auto_start_selection);
+SIMPLE_FUNCTION(start_selection);
+SIMPLE_FUNCTION(end_selection);
+SIMPLE_FUNCTION(select_all);
+SIMPLE_FUNCTION(unselect_all);
+COMPLEX_FUNCTION(scroll_horizontal, int, float);
+NAME_ARGS(scroll_type, position);
+COMPLEX_FUNCTION(scroll_vertical, int, float);
+NAME_ARGS(scroll_type, position);
+SIMPLE_FUNCTION(toggle_add_mode);
+SIMPLE_FUNCTION(toggle_focus_row);
+COMPLEX_FUNCTION(toggle_row, widget);
+NAME_ARGS(child);
+SIMPLE_FUNCTION(undo_selection);
+SIMPLE_FUNCTION(end_drag_selection);
+
+FUNCTION(insert_items, "function(array(object),int:object)");
+ARGS(array(GTK.ListItem),int);
+NAME_ARGS(items,position);
+{
+  struct array *a;
+  int p;
+  GList *items = NULL;
+  int i;
+  get_all_args("insert_items", args, "%a%d", &a, &p);
+  
+  for(i=0; i<a->size; i++)
+    if(a->item[i].type == T_OBJECT &&
+       get_pgtkobject( a->item[i].u.object, pgtk_list_item_program ))
+      g_list_prepend(items, get_pgtkobject(a->item[i].u.object,
+                                           pgtk_list_item_program));
+  if(items)
+    gtk_list_insert_items( GTK_LIST( THIS->obj ), items, p );
+  g_list_free( items );
+  RETURN_THIS();
+}
+
+FUNCTION(append_items, "function(array(object):object)");
+ARGS(array(GTK.ListItem),int);
+NAME_ARGS(items,position);
+{
+  struct array *a;
+  GList *items = NULL;
+  int i;
+  get_all_args("append_items", args, "%a", &a);
+  
+  for(i=0; i<a->size; i++)
+    if(a->item[i].type == T_OBJECT &&
+       get_pgtkobject( a->item[i].u.object, pgtk_list_item_program ))
+      g_list_prepend(items, get_pgtkobject(a->item[i].u.object,
+                                           pgtk_list_item_program));
+  if(items)
+    gtk_list_append_items( GTK_LIST( THIS->obj ), items );
+  g_list_free( items );
+  RETURN_THIS();
+}
+
+FUNCTION(prepend_items, "function(array(object):object)");
+ARGS(array(GTK.ListItem),int);
+NAME_ARGS(items,position);
+{
+  struct array *a;
+  GList *items = NULL;
+  int i;
+  get_all_args("prepend_items", args, "%a", &a);
+  
+  for(i=0; i<a->size; i++)
+    if(a->item[i].type == T_OBJECT &&
+       get_pgtkobject( a->item[i].u.object, pgtk_list_item_program ))
+      g_list_prepend(items, get_pgtkobject(a->item[i].u.object,
+                                           pgtk_list_item_program));
+  if(items)
+    gtk_list_prepend_items( GTK_LIST( THIS->obj ), items );
+  g_list_free( items );
+  RETURN_THIS();
+}
+
+FUNCTION(remove_items, "function(array(object):object)");
+ARGS(array(GTK.ListItem),int);
+NAME_ARGS(items,position);
+{
+  struct array *a;
+  GList *items = NULL;
+  int i;
+  get_all_args("remove_items", args, "%a", &a);
+  
+  for(i=0; i<a->size; i++)
+    if(a->item[i].type == T_OBJECT &&
+       get_pgtkobject( a->item[i].u.object, pgtk_list_item_program ))
+      g_list_prepend(items, get_pgtkobject(a->item[i].u.object,
+                                           pgtk_list_item_program));
+  if(items)
+    gtk_list_remove_items( GTK_LIST( THIS->obj ), items );
+  g_list_free( items );
+  RETURN_THIS();
+}
+
+
+COMPLEX_FUNCTION(clear_items, int, int);
+NAME_ARGS(start,end);
+COMPLEX_FUNCTION(select_item, int);
+NAME_ARGS(item);
+COMPLEX_FUNCTION(unselect_item, int);
+NAME_ARGS(item);
+COMPLEX_FUNCTION(select_child, widget);
+NAME_ARGS(child);
+COMPLEX_FUNCTION(unselect_child, widget);
+NAME_ARGS(child);
+COMPLEX_FUNCTION(set_selection_mode, int);
+NAME_ARGS(selection_mode);
+
+SUBWIDGET(last_focus_child, list_item);
+SUBWIDGET(undo_focus_child, list_item);
+
+CLASSMEMBER(htimer,int);
+CLASSMEMBER(vtimer,int);
+CLASSMEMBER(anchor,int);
+CLASSMEMBER(drag_pos,int);
+CLASSMEMBER(anchor_state,int);
+CLASSMEMBER(selection_mode,int);
+CLASSMEMBER(drag_selection,int);
+CLASSMEMBER(add_mode,int);
diff --git a/src/post_modules/GTK/source/gtklistitem.pre b/src/post_modules/GTK/source/gtklistitem.pre
new file mode 100644
index 0000000000000000000000000000000000000000..b0e19810d5caa49e4422f7de61d706c1352d1585
--- /dev/null
+++ b/src/post_modules/GTK/source/gtklistitem.pre
@@ -0,0 +1,25 @@
+PROGRAM(list_item);
+// This type of items can be placed in a 'List' widget. 
+INHERIT(item);
+FUNCTION(create, "function(string|void:void)");
+NAME_ARGS(label);
+// If a string is supplied, a W(Label) widget is created using that
+// string and added to the item. Otherwise, you should add another
+// widget to the list item with -&gt;add().
+{
+  if(THIS->obj) error("GTK.List_item->create() can only be called once.\n");
+  if(args)
+  {
+    char *s;
+    get_all_args("GTK.List_item", args, "%s", &s);
+    THIS->obj = GTK_OBJECT( gtk_list_item_new_with_label( s ) );
+  } else {
+    THIS->obj = GTK_OBJECT( gtk_list_item_new( ) );
+  }
+  pgtk__init_this_object();
+}
+SIMPLE_FUNCTION(select);
+// Emulate a select event
+SIMPLE_FUNCTION(deselect);
+// Emulate a deselect event
+
diff --git a/src/post_modules/GTK/source/gtkmenu.pre b/src/post_modules/GTK/source/gtkmenu.pre
new file mode 100644
index 0000000000000000000000000000000000000000..ff2db30f64ce7b24e7feeef6017830961b0f20ad
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkmenu.pre
@@ -0,0 +1,107 @@
+PROGRAM(menu);
+// A GTK.Menu is a W(MenuShell) that implements a drop down menu
+// consisting of a list of W(MenuItem) objects which can be navigated
+// and activated by the user to perform application functions.
+
+// <p>
+
+// A GTK.Menu is most commonly dropped down by activating a W(MenuItem)
+// in a W(MenuBar) or popped up by activating a W(MenuItem) in another
+// GTK.Menu.
+
+// <p>
+
+// A GTK.Menu can also be popped up by activating a
+// W(OptionMenu). Other composite widgets such as the W(Notebook) can
+// pop up a GTK.Menu as well.
+
+// <p>
+
+// Applications can display a GTK.Menu as a popup menu by calling the
+// popup() function. The example below shows how an application can
+// pop up a menu when the 3rd mouse button is pressed.
+
+// <p>
+
+// <pre><font size=-1>
+// &nbsp; GTK.Menu menu = create_menu();
+// &nbsp; GTK.Window window = create_window();
+// &nbsp; window->signal_connect( "button_press_event", lambda(GTK.Menu m,
+// &nbsp;                                                      GTK.Window w,
+// &nbsp;                                                      mapping e ) {
+// &nbsp;           if( e->button == 3 )
+// &nbsp;            menu->popup();
+// &nbsp;        }, menu );
+// <font size=-1></pre>
+INHERIT(menu_shell);
+FUNCTION(popup, "function(int|void:object)")
+RETURNS(GTK.Menu);
+NAME_ARGS(button_pressed_to_show_menu);
+// The default button is 3.
+{
+  int button = 3;
+  if( args )
+    get_all_args( "popup", args, "%d", &button );
+  gtk_menu_popup(GTK_MENU(THIS->obj), NULL,NULL,NULL,NULL, button, time(0));
+  RETURN_THIS();
+}
+
+SIMPLE_FUNCTION(reposition);
+// Repositions the menu according to its position function.
+
+SIMPLE_FUNCTION(popdown);
+// Removes the menu from the screen.
+
+COMPLEX_FUNCTION(set_accel_group, accel_group);
+NAME_ARGS(accelerators);
+// Set the W(AccelGroup) which holds global accelerators for the menu.
+
+COMPLEX_FUNCTION(create);
+// Create a new GTK.Menu widget.
+
+COMPLEX_FUNCTION(append, widget);
+NAME_ARGS(widget);
+// Adds a new W(MenuItem) to the end of the menu's item list.
+
+COMPLEX_FUNCTION(prepend, widget);
+NAME_ARGS(widget);
+// Adds a new W(MenuItem) to the start of the menu's item list.
+
+COMPLEX_FUNCTION(insert, widget, int);
+NAME_ARGS(widget,position);
+// Adds a new W(MenuItem) to the menu's item list at the position
+// indicated by position.
+COMPLEX_FUNCTION(set_active, int);
+NAME_ARGS(activep);
+// Selects the specified menu item within the menu. This is used by
+// the W(OptionMenu).
+
+COMPLEX_FUNCTION(reorder_child, widget, int);
+NAME_ARGS(menuitem,pos);
+// Moves a W(MenuItem) to a new position within the GTK.Menu.
+
+SIMPLE_FUNCTION(detach);
+//  Detaches the menu from the widget to which it had been attached. 
+COMPLEX_FUNCTION(attach_to_widget, widget, NULL);
+NAME_ARGS(widget);
+// Attach the menu to a widget
+COMPLEX_FUNCTION(set_title, string);
+NAME_ARGS(new_title);
+// Sets the title string for the menu. The title is displayed when the
+// menu is shown as a tearoff menu.
+
+widget COMPLEX_FUNCTION(get_active);
+// Returns the selected menu item from the menu.<br>
+//  This is used by the W(OptionMenu).
+
+widget COMPLEX_FUNCTION(get_attach_widget);
+// Returns the W(Widget) that the menu is attached to.
+COMPLEX_FUNCTION(set_tearoff_state, int);
+NAME_ARGS(torn_off);
+// Changes the tearoff state of the menu. A menu is normally displayed
+// as drop down menu which persists as long as the menu is active. It
+// can also be displayed as a tearoff menu which persists until it is
+// closed or reattached.
+
+CLASSMEMBER(torn_off, int);
+// return 1 if the menu is torn off.
diff --git a/src/post_modules/GTK/source/gtkmenubar.pre b/src/post_modules/GTK/source/gtkmenubar.pre
new file mode 100644
index 0000000000000000000000000000000000000000..e0854df7f5c6e3882da228c696e2e2ded479aa03
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkmenubar.pre
@@ -0,0 +1,16 @@
+PROGRAM(menu_bar);
+// Basically a horizontal W(Menu)<p>
+// The menu image cannot be
+// grabbed automatically, but this is how you would create a menu all
+// in one line. This is not the recommended coding style.<p>
+// IMG: GTK.MenuBar()->add(GTK.Menu_item("Menu")->set_submenu(GTK.Menu()->add(GTK.Menu_item("Sub")))->select()->activate())->add(GTK.Menu_item("Bar"))
+INHERIT(menu_shell);
+COMPLEX_FUNCTION(create);
+COMPLEX_FUNCTION(append, widget);
+NAME_ARGS(menu);
+COMPLEX_FUNCTION(prepend, widget);
+NAME_ARGS(menu);
+COMPLEX_FUNCTION(insert, widget, int);
+NAME_ARGS(menu,position);
+COMPLEX_FUNCTION(set_shadow_type, int);
+NAME_ARGS(int);
diff --git a/src/post_modules/GTK/source/gtkmenuitem.pre b/src/post_modules/GTK/source/gtkmenuitem.pre
new file mode 100644
index 0000000000000000000000000000000000000000..6294fb84dbcb9047e2f57f20e8d04f32ffe31143
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkmenuitem.pre
@@ -0,0 +1,56 @@
+PROGRAM(menu_item);
+// Menu items, to be added to menues.
+// <p>
+INHERIT(item);
+FUNCTION(create, "function(string|void:void)")
+NAME_ARGS(label);
+// If a string is supplied, a W(Label) widget is created using that
+// string and added to the item. Otherwise, you should add another
+// widget to the list item with -&gt;add().
+{
+  if(THIS->obj) error("GTK.Menu_item->create() can only be called once.\n");
+  if(args)
+  {
+    char *s;
+    get_all_args("GTK.Menu_item", args, "%s", &s);
+    THIS->obj = GTK_OBJECT( gtk_menu_item_new_with_label( s ) );
+  } else {
+    THIS->obj = GTK_OBJECT( gtk_menu_item_new( ) );
+  }
+  pgtk__init_this_object();
+}
+
+COMPLEX_FUNCTION(set_submenu, widget);
+NAME_ARGS(menu);
+// Set the submenu for this menu button.
+COMPLEX_FUNCTION(remove_submenu);
+// Remove the submenu for this menu button.
+COMPLEX_FUNCTION(set_placement,int);
+NAME_ARGS(dir);
+// (sub menu placement) One of CONST(GTK_DIRECTION)
+COMPLEX_FUNCTION(configure, int,int);
+NAME_ARGS(toggle_indicator, submenu_indicator);
+// First argument is 'show_toggle_indicator', second is
+// 'show_submenu_indicator'.
+SIMPLE_FUNCTION(select);
+// Emulate a select signal
+SIMPLE_FUNCTION(deselect);
+// Emulate a deselect signal
+SIMPLE_FUNCTION(activate);
+// Emulate an activate signal
+SIMPLE_FUNCTION(right_justify);
+// Make the menu item stick to the right edge of it's container.
+CLASSMEMBER(right_justify, int);
+// Is the widget right justified?
+CLASSMEMBER(submenu_direction, int);
+// The direction the submenu will be shown in. One of CONST(GTK_DIR_)
+CLASSMEMBER(submenu_placement, int);
+// The placement of the submenu. 
+CLASSMEMBER(show_submenu_indicator, int);
+// Should the submenu indicator be shown?
+CLASSMEMBER(show_toggle_indicator, int);
+// Should the toggle indicator be shown?
+CLASSMEMBER(toggle_size, int);
+// The size of the toggle indicator
+CLASSMEMBER(accelerator_width, int);
+// The width of the accelerator string, in pixels
diff --git a/src/post_modules/GTK/source/gtkmenushell.pre b/src/post_modules/GTK/source/gtkmenushell.pre
new file mode 100644
index 0000000000000000000000000000000000000000..14eba8f93fd2c3e85b1609c47a301b6c9dfe7ef0
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkmenushell.pre
@@ -0,0 +1,61 @@
+PROGRAM(menu_shell);
+
+// A GTK.MenuShell is the abstract base class used to derive the
+// W(Menu) and W(MenuBar) subclasses.
+
+// <p>
+
+// A GTK.MenuShell is a container of W(MenuItem) objects arranged in a
+// list which can be navigated, selected, and activated by the user to
+// perform application functions. A W(MenuItem) can have a submenu
+// associated with it, allowing for nested hierarchical menus.
+
+SIGNAL("deactivate","This signal is emitted when a menu shell is deactivated.");
+SIGNAL("selection_done","This signal is emitted when a selection has been completed within a menu shell.");
+SIGNAL("move_current", "An action signal which moves the current menu item in the direction specified by the third argument.");
+SIGNAL("activate_current","An action signal that activates the current menu item within the menu shell.");
+SIGNAL("cancel","An action signal which cancels the selection within the menu shell. Causes the selection_done signal to be emitted.");
+INHERIT(container);
+
+CLASSMEMBER(active, int);
+// 1 if the menu shell is currently active.
+
+COMPLEX_FUNCTION(append, widget);
+NAME_ARGS(what);
+// Adds a new W(MenuItem) to the end of the menu shell's item
+// list. Same as 'add'.
+
+COMPLEX_FUNCTION(prepend, widget);
+NAME_ARGS(what);
+// Add a menu item to the start of the widget (for a menu: top, for a
+// bar: left)
+COMPLEX_FUNCTION(insert, widget, int);
+NAME_ARGS(what,where);
+// Add a widget after the specified location
+COMPLEX_FUNCTION(deactivate);
+// Deactivates the menu shell. Typically this results in the menu
+// shell being erased from the screen.
+COMPLEX_FUNCTION(select_item, widget);
+NAME_ARGS(menuitem);
+// Selects the menu item from the menu shell.
+COMPLEX_FUNCTION(activate_item, widget, int);
+NAME_ARGS(menu_item, force_deactivate);
+// Activates the menu item within the menu shell.
+
+FUNCTION(children, "function(void:array(object))");
+RETURNS(array(GTK.MenuItem));
+// This function returns all children of the container
+// as an array.
+{
+  GList *g;
+  int n = 0;
+  pop_n_elems(args);
+  g = GTK_MENU_SHELL( THIS->obj )->children;
+  while(g)
+  {
+    push_gtkobjectclass( GTK_OBJECT( g->data ), pgtk_menu_item_program );
+    n++;
+    g = g->next;
+  }
+  f_aggregate(n);
+}
diff --git a/src/post_modules/GTK/source/gtkmisc.pre b/src/post_modules/GTK/source/gtkmisc.pre
new file mode 100644
index 0000000000000000000000000000000000000000..1efde3c6f2e30d1f40704bea15033e73ae6abd47
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkmisc.pre
@@ -0,0 +1,34 @@
+PROGRAM(misc);
+// The GTK.Misc widget is an abstract widget which is not useful
+// itself, but is used to derive subclasses which have alignment and
+// padding attributes.
+// <p>
+// The horizontal and vertical padding attributes allows extra space
+// to be added around the widget.
+// <p>
+// The horizontal and vertical alignment attributes enable the widget
+// to be positioned within its allocated area. Note that if the widget
+// is added to a container in such a way that it expands automatically
+// to fill its allocated area, the alignment settings will not alter
+// the widgets position.
+//
+// IMG: GTK.Vbox(0,0)->add(GTK.Label("Label"))->set_usize(100,20)
+// IMG: GTK.Vbox(0,0)->add(GTK.Label("Label")->set_alignment(1.0,0.0))->set_usize(100,20)
+// IMG: GTK.Vbox(0,0)->add(GTK.Label("Label")->set_alignment(0.0,0.0))->set_usize(100,20)
+INHERIT(widget);
+COMPLEX_FUNCTION(set_alignment, float, float);
+NAME_ARGS(xalign,yalign);
+// Sets the alignment of the widget.
+// 0.0 is left or topmost, 1.0 is right or bottommost.
+COMPLEX_FUNCTION(set_padding, int, int);
+NAME_ARGS(xpad,ypad);
+// Sets the amount of space to add around the widget. xpand and ypad
+// are specified in pixels.
+CLASSMEMBER(xalign, float);
+// The horizontal alignment, from 0 (left) to 1 (right).
+CLASSMEMBER(yalign, float);
+// The vertical alignment, from 0 (top) to 1 (botton).
+CLASSMEMBER(xpad, int);
+// The amount of space to add on the left and right of the widget, in pixels.
+CLASSMEMBER(ypad, int);
+// The amount of space to add on the top and bottom of the widget, in pixels.
diff --git a/src/post_modules/GTK/source/gtknotebook.pre b/src/post_modules/GTK/source/gtknotebook.pre
new file mode 100644
index 0000000000000000000000000000000000000000..ea036a350d68c4179b3559f6d10df21a4e2dd705
--- /dev/null
+++ b/src/post_modules/GTK/source/gtknotebook.pre
@@ -0,0 +1,133 @@
+PROGRAM(notebook);
+// The NoteBook Widget is a collection of 'pages' that overlap each
+// other, each page contains different information. This widget has
+// become more common lately in GUI programming, and it is a good way
+// to show blocks similar information that warrant separation in their
+// display.
+//
+// IMG: GTK.Notebook( )->set_tab_pos( GTK.POS_LEFT )->append_page( GTK.Label("Page 1\nContents"), GTK.Label("Page 1"))->append_page( GTK.Label(""), GTK.Label("Page 2"))->append_page(GTK.Label("Page 3 contents\nare here!"), GTK.Label("Page 3"))
+// IMG: GTK.Notebook( )->set_tab_pos( GTK.POS_TOP )->append_page( GTK.Label("Page 1\nContents"), GTK.Label("Page 1"))->append_page( GTK.Label(""), GTK.Label("Page 2"))->append_page(GTK.Label("Page 3 contents\nare here!"), GTK.Label("Page 3"))
+// IMG: GTK.Notebook( )->set_tab_pos( GTK.POS_RIGHT )->append_page( GTK.Label("Page 1\nContents"), GTK.Label("Page 1"))->append_page( GTK.Label(""), GTK.Label("Page 2"))->append_page(GTK.Label("Page 3 contents\nare here!"), GTK.Label("Page 3"))->next_page()->next_page()
+SIGNAL("switch_page", "Called when a different page is selected");
+INHERIT(container);
+COMPLEX_FUNCTION(create);
+COMPLEX_FUNCTION(append_page, widget, widget);
+NAME_ARGS(contents,label);
+// Add a new 'page' to the notebook. The first argument is the contents of
+// the page, the second argument is the label.
+COMPLEX_FUNCTION(append_page_menu, widget, widget, widget);
+NAME_ARGS(contents,label,mennu);
+// Add a new 'page' to the notebook. The first argument is the
+// contents of the page, the second argument is the label, the third
+// argument is a menu widget.
+COMPLEX_FUNCTION(prepend_page, widget, widget);
+NAME_ARGS(contents,label);
+// Add a page at the end of the list of pages. The first argument is
+// the contents of the page, the second argument is the label.
+COMPLEX_FUNCTION(prepend_page_menu, widget, widget, widget);
+NAME_ARGS(contents,label,menu);
+// Add a new 'page' at the end of the list of pages. The first
+// argument is the contents of the page, the second argument is the
+// label, the third argument is a menu widget.
+COMPLEX_FUNCTION(insert_page, widget, widget, int);
+NAME_ARGS(contents,label,pos);
+// Insert a page at the specified location, arguments as for
+// append_page, but an aditional integer specifies the location.
+
+COMPLEX_FUNCTION(insert_page_menu, widget, widget, widget, int);
+NAME_ARGS(contents,label,menu,pos);
+// Insert a page at the specified location, arguments as for
+// append_page_menu, but an aditional integer specifies the location.
+
+COMPLEX_FUNCTION(remove_page, int);
+NAME_ARGS(pos);
+// Remove a page.
+
+int COMPLEX_FUNCTION(get_current_page);
+//  Returns the index of the currently selected page
+widget COMPLEX_FUNCTION(get_nth_page, int);
+NAME_ARGS(index);
+//  Returns the page for the specified index
+int COMPLEX_FUNCTION(page_num, widget);
+NAME_ARGS(widget);
+//  Returns the index for the specified page
+COMPLEX_FUNCTION(set_page, int);
+NAME_ARGS(pos);
+// Go to the specified page
+SIMPLE_FUNCTION(next_page);
+// Go to the next page
+SIMPLE_FUNCTION(prev_page);
+// Go to the previous page
+COMPLEX_FUNCTION(set_tab_pos, int);
+NAME_ARGS(pos);
+// One of CONST(GTK_POS)
+COMPLEX_FUNCTION(set_show_tabs, int);
+NAME_ARGS(showtabsp);
+// If supplied with a true value, the tabs will be shown. Otherwise
+// they will not be shown. The user will not be able to select the
+// pages without them, but you can add 'next' and 'previous' buttons
+// to create a wizard-line interface.
+COMPLEX_FUNCTION(set_homogeneous_tabs, int);
+NAME_ARGS(homogeneousp);
+// If true, all tabs will have the same size
+COMPLEX_FUNCTION(set_show_border, int);
+NAME_ARGS(showborderp);
+// If true, show the borders around the contents and tabs.
+COMPLEX_FUNCTION(set_scrollable, int);
+NAME_ARGS(scrollablep);
+// If true, add scrollbars if nessesary.
+COMPLEX_FUNCTION(set_tab_border, int);
+NAME_ARGS(border_width);
+// In pixels. 
+COMPLEX_FUNCTION(set_tab_hborder, int);
+NAME_ARGS(border_width);
+// In pixels. 
+COMPLEX_FUNCTION(set_tab_vborder, int);
+NAME_ARGS(border_width);
+// In pixels. 
+SIMPLE_FUNCTION(popup_enable);
+// Enable the popup menu (set with insert_page_menu)
+SIMPLE_FUNCTION(popup_disable);
+// Disable the popup menu (set with insert_page_menu)
+
+widget COMPLEX_FUNCTION(get_tab_label, widget);
+NAME_ARGS(page);
+COMPLEX_FUNCTION(set_tab_label, widget, widget);
+NAME_ARGS(page,label);
+COMPLEX_FUNCTION(set_tab_label_text, widget, string);
+NAME_ARGS(page,title);
+widget COMPLEX_FUNCTION(get_menu_label, widget);
+NAME_ARGS(page);
+COMPLEX_FUNCTION(set_menu_label, widget, widget);
+NAME_ARGS(page,label);
+COMPLEX_FUNCTION(set_menu_label_text, widget, string);
+NAME_ARGS(page,label);
+COMPLEX_FUNCTION(set_tab_label_packing, widget, int,int,int);
+NAME_ARGS(child,expand,fill,type);
+
+FUNCTION(query_tab_label_packing, "function(object:mapping)");
+NAME_ARGS(page);
+// Returns ([ "expand":expandp, "fill":fillp, "pack_type":type ])
+{
+  struct object *o;
+  gboolean expand=0, fill=0;
+  GtkPackType pack_type=0;
+  get_all_args( "query_tab_label_packing", args, "%o", &o );
+  gtk_notebook_query_tab_label_packing( GTK_NOTEBOOK( THIS->obj ), 
+                                        GTK_WIDGET( get_gtkobject( o ) ),
+                                        &expand,
+                                        &fill,
+                                        &pack_type );
+  pop_n_elems(args);
+  push_text( "expand" );
+  push_int( expand );
+  push_text( "fill" );
+  push_int( fill );
+  push_text( "pack_type" );
+  push_int( pack_type );
+  f_aggregate_mapping( 6 );
+}
+
+COMPLEX_FUNCTION(reorder_child, widget, int);
+NAME_ARGS(page, new_index);
+// Move the specified page to the index new_index
diff --git a/src/post_modules/GTK/source/gtkobject.pre b/src/post_modules/GTK/source/gtkobject.pre
new file mode 100644
index 0000000000000000000000000000000000000000..18d7f90fe893439ba77780b7b543e9a19a7e1b72
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkobject.pre
@@ -0,0 +1,111 @@
+/* -*- c -*- */
+
+PROGRAM(object);
+// The basic GTK class.
+// All other GTK classes inherit this class.
+// The only user-callable functions are the signal related ones.
+SIGNAL("destroy", "Called when the object is destroyed");
+
+
+FUNCTION(destroy, "function(void:void)");
+{
+  if(!args && THIS->obj)
+  {
+    gtk_object_destroy( THIS->obj );
+    THIS->obj = NULL;
+  }
+  pop_n_elems(args);
+  push_int(0);
+}
+
+
+FUNCTION(signal_emit_stop, "function(string:object)")
+RETURNS(GTK.Object);
+NAME_ARGS(signal_name);
+// Halt the emit of the current named signal.
+// Useful in signal handlers when you want to override the behaviour
+// of some default signal handler (key press events, as an example)
+// See signal_connect.
+{
+  char *s;
+  get_all_args("signal_emit_stop", args, "%s", &s);
+  gtk_signal_emit_stop_by_name( GTK_OBJECT(THIS->obj), s);
+  RETURN_THIS();
+}
+
+FUNCTION(signal_disconnect, "function(mixed:object)");
+RETURNS(GTK.Object);
+NAME_ARGS(signal_id);
+// Remove a signal formerly added by signal_connect. The argument is
+// the return value of signal_connect(). See signal connect for more info.
+{
+  int i;
+  get_all_args("signal_disconnect", args, "%d", &i);
+  gtk_signal_disconnect( GTK_OBJECT( THIS->obj ), i );
+}
+
+FUNCTION(signal_block, "function(mixed:object)");
+RETURNS(GTK.Object);
+NAME_ARGS(signal_id);
+// Temporarily block a signal handler. No signals will be received
+// while the hander is blocked.
+// See signal connect for more info.
+{
+  int i;
+  get_all_args("signal_block", args, "%d", &i);
+  gtk_signal_handler_block( GTK_OBJECT( THIS->obj ), i );
+}
+
+FUNCTION(signal_unblock, "function(mixed:object)");
+RETURNS(GTK.Object);
+NAME_ARGS(signal_id);
+// Unblock a formerly blocked signal handler. See signal_block and
+// signal_connect for more info.
+{
+  int i;
+  get_all_args("signal_unblock", args, "%d", &i);
+  gtk_signal_handler_unblock( GTK_OBJECT( THIS->obj ), i );
+}
+
+FUNCTION(signal_connect, "function(string,function,mixed|void:mixed)");
+NAME_ARGS(signal_name,callback_function,callback_arg);
+// Connect a signal to a pike function. The function will be called with
+// the last argument to this function as it's first argument (defaults 
+// to 0), the second argument is always the widget, any other
+// arguments are the ones supplied by GTK.
+// <p>
+// The return value of this function can be used to remove a signal
+// with signal_disconnect, and block and unblock the signal will
+// signal_block and signal_unblock.
+{
+  char *a;
+  int id;
+  struct signal_data *b;
+  struct svalue *tmp1, *tmp2;
+  guint signal_id;
+  b = malloc(sizeof(struct signal_data));
+  if(args == 2)
+  {
+    push_int( 0 );
+    args++;
+  }
+  get_all_args("signal_connect", args, "%s%*%*", &a, &tmp1, &tmp2 );
+
+  assign_svalue_no_free( &b->cb, tmp1 );
+  assign_svalue_no_free( &b->args, tmp2 );
+  
+  signal_id = gtk_signal_lookup (a, GTK_OBJECT_TYPE (THIS->obj));
+  if(!signal_id)
+  {
+    free(b);
+    error("Signal \"%s\" not defined in the `%s' class ancestry\n",
+	  a, gtk_type_name (GTK_OBJECT_TYPE(THIS->obj)));
+  }
+  id = gtk_signal_connect_full(THIS->obj, a, 0, 
+                               (void *)pgtk_signal_func_wrapper, b,
+			       (void *)pgtk_free_signal_data, FALSE, FALSE);
+  pop_n_elems(args);
+  push_int( id );
+}
+
+
diff --git a/src/post_modules/GTK/source/gtkoptionmenu.pre b/src/post_modules/GTK/source/gtkoptionmenu.pre
new file mode 100644
index 0000000000000000000000000000000000000000..7264d87a32f45bd23cf17089d521c670f63d7236
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkoptionmenu.pre
@@ -0,0 +1,23 @@
+PROGRAM(option_menu);
+// A OptionMenu is a widget that allows the user to choose from a
+// list of valid choices. The OptionMenu displays the selected
+// choice. When activated the OptionMenu displays a popup W(Menu)
+// which allows the user to make a new choice.
+// <p>
+// IMG: GTK.OptionMenu()->set_menu(GTK.Menu()->add( GTK.Menu_item("Option 1") ));
+INHERIT(button);
+COMPLEX_FUNCTION(create);
+// Create a new option menu widget
+COMPLEX_FUNCTION(set_menu, menu);
+NAME_ARGS(menu);
+// Provides the GtkMenu that is popped up to allow the user to choose
+// a new value. You should provide a simple menu avoiding the use of
+// tearoff menu items, submenus, and accelerators.
+SIMPLE_FUNCTION(remove_menu);
+// Remove the menu.
+COMPLEX_FUNCTION(set_history, int);
+NAME_ARGS(index);
+// Selects the menu item specified by index making it the newly
+// selected value for the option menu.
+menu COMPLEX_FUNCTION(get_menu);
+// Returns the W(Menu) associated with the OptionMenu.
diff --git a/src/post_modules/GTK/source/gtkpacker.pre b/src/post_modules/GTK/source/gtkpacker.pre
new file mode 100644
index 0000000000000000000000000000000000000000..9f9472fc99a02796bebea0e6b0f262fa4c87e29d
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkpacker.pre
@@ -0,0 +1,41 @@
+PROGRAM(packer);
+INHERIT(container);
+COMPLEX_FUNCTION(create);
+
+COMPLEX_FUNCTION(add_defaults, widget, int, int, int);
+NAME_ARGS(widget, side, anchor, options);
+// side is one of CONST(GTK_SIDE), anchor is one of CONST(GTK_ANCHOR),
+// options is a bitwise or of GTK.PackExpand, GTK.FillX and GTK.FillY
+
+COMPLEX_FUNCTION(add, widget, int, int, int,int,int,int,int,int);
+NAME_ARGS(widget, side, anchor, options,border_width,pad_x,pad_y,i_pad_x,i_pad_y);
+// side is one of CONST(GTK_SIDE), anchor is one of CONST(GTK_ANCHOR),
+// options is a bitwise or of GTK.PackExpand, GTK.FillX and GTK.FillY
+
+COMPLEX_FUNCTION(set_child_packing, widget, int, int, int,int,int,int,int,int);
+NAME_ARGS(child, side, anchor, options,border_width,pad_x,pad_y,i_pad_x,i_pad_y);
+// side is one of CONST(GTK_SIDE), anchor is one of CONST(GTK_ANCHOR),
+// options is a bitwise or of GTK.PackExpand, GTK.FillX and GTK.FillY
+
+COMPLEX_FUNCTION(reorder_child, widget, int);
+NAME_ARGS(child,pos);
+
+COMPLEX_FUNCTION(set_spacing, int);
+NAME_ARGS(new_spacing);
+
+COMPLEX_FUNCTION(set_default_border_width, int);
+NAME_ARGS(border);
+
+COMPLEX_FUNCTION(set_default_pad, int, int);
+NAME_ARGS(xpad,ypad);
+
+COMPLEX_FUNCTION(set_default_ipad, int, int);
+NAME_ARGS(xpad,ypad);
+
+
+CLASSMEMBER(spacing, int);
+CLASSMEMBER(default_border_width, int);
+CLASSMEMBER(default_pad_x, int);
+CLASSMEMBER(default_pad_y, int);
+CLASSMEMBER(default_i_pad_x, int);
+CLASSMEMBER(default_i_pad_y, int);
diff --git a/src/post_modules/GTK/source/gtkpaned.pre b/src/post_modules/GTK/source/gtkpaned.pre
new file mode 100644
index 0000000000000000000000000000000000000000..75893981f537e2447316ef825005bd464f238dd0
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkpaned.pre
@@ -0,0 +1,76 @@
+PROGRAM(paned);
+// GTK.Paned is the base class for widgets with two panes, arranged
+// either horizontally (W(HPaned)) or vertically (W(VPaned)). Child
+// widgets are added to the panes of the widget with pack1() and
+// pack2(). The division beween the two children is set by default
+// from the size requests of the children, but it can be adjusted by
+// the user.
+
+// <p>
+
+// A paned widget draws a separator between the two child widgets and
+// a small handle that the user can drag to adjust the division. It
+// does not draw any relief around the children or around the
+// separator. (The space in which the separator is called the
+// gutter). Often, it is useful to put each child inside a W(Frame)
+// with the shadow type set to GTK.ShadowIn so that the gutter
+// appears as a ridge.
+
+// <p>
+
+// Each child has two options that can be set, resize and shrink. If
+// resize is true, then when the GTK.Paned is resized, that child will
+// expand or shrink along with the paned widget. If shrink is true,
+// then when that child can be made smaller than it's requisition by
+// the user. Setting shrink to 0 allows the application to set a
+// minimum size. If resize is false for both children, then this is
+// treated as if resize is true for both children.
+
+// <p>
+
+// The application can set the position of the slider as if it were
+// set by the user, by calling set_position().
+INHERIT(container);
+COMPLEX_FUNCTION(add1, widget);
+NAME_ARGS(left_or_top);
+// Set the left or topmost item.<br>
+// This is equivalent to pack1(left_or_top,0,1)
+COMPLEX_FUNCTION(add2, widget);
+NAME_ARGS(right_or_bottom);
+// Set the right or bottommost item<br>
+// This is equivalent to pack2(left_or_top,0,1)
+COMPLEX_FUNCTION(set_handle_size, int);
+NAME_ARGS(hsize);
+// The size of the handle in pixels
+COMPLEX_FUNCTION(set_gutter_size, int);
+NAME_ARGS(gsize);
+// Set the width of the gutter. (The area between the two panes).
+COMPLEX_FUNCTION(set_position, int);
+NAME_ARGS(position);
+// Set the position of the separator, as if set by the user. If
+// position is negative, the remembered position is forgotten, and
+// the division is recomputed from the the requisitions of the
+// children.
+COMPLEX_FUNCTION(pack1, widget, int, int);
+NAME_ARGS(widget,resize, shrink);
+// Add a child to the top or left pane.
+COMPLEX_FUNCTION(pack2, widget, int, int);
+NAME_ARGS(widget,resize, shrink);
+// Add a child to the bottom or right pane.
+CLASSMEMBER(handle_size, int);
+// The size of the handle, in pixels
+CLASSMEMBER(gutter_size, int);
+// The size of the gutter, in pixels
+
+CLASSMEMBER(handle_xpos, int);
+// The xpos of the handle, in pixels
+CLASSMEMBER(handle_ypos, int);
+// The ypos of the handle, in pixels
+
+CLASSMEMBER(min_position, int);
+// The minimum handle position possible.
+CLASSMEMBER(max_position, int);
+// The maximum handle position possible.
+
+CLASSMEMBER(in_drag, int);
+// Return 1 if the user is dragging the handle
diff --git a/src/post_modules/GTK/source/gtkpixmap.pre b/src/post_modules/GTK/source/gtkpixmap.pre
new file mode 100644
index 0000000000000000000000000000000000000000..722ea43faa048aeac957205a76ea30857b9ed43d
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkpixmap.pre
@@ -0,0 +1,135 @@
+PROGRAM(pixmap);
+INHERIT(misc);
+// Pixmaps are data structures that contain pictures. These pictures
+// can be used in various places, but most visibly as icons on the
+// X-Windows desktop, or as cursors. A bitmap is a 2-color pixmap.
+// <p>
+// To use pixmaps in GTK, you must first build a GDK.Pixmap object
+// using GDK.Pixmap.
+
+// <p>
+
+// The pixels in a GTK.Pixmap cannot be manipulated by the application
+// after creation, since under the X Window system the pixel data is
+// stored on the X server and so is not available to the client
+// application. If you want to create graphical images which can be
+// manipulated by the application, look at W(Image).
+
+// <p>
+
+// IMG: GTK.Pixmap( GDK.Pixmap( Image.image(100,100)->test()) )
+// IMG: GTK.Pixmap( GDK.Pixmap( Image.image(100,100)->test()), GDK.Bitmap(Image.image(100,100,255,255,255)->box(10,10,80,80, 0,0,0) ))
+
+FUNCTION(create, "function(object,object|void:void)");
+ARGS(GDK.Pixmap,GDK.Bitmap);
+NAME_ARGS(pixmap,mask);
+// Create a new pixmap object.
+{
+  struct object *a, *b;
+  GdkPixmap *img;
+  GdkBitmap *mask = NULL;
+  if(args == 2)
+    get_all_args("GDK.Pixmap", args, "%o%o", &a, &b);
+  else
+  {
+    get_all_args("GDK.Pixmap", args, "%o", &a);
+    b = 0;
+  }
+  img = get_gdkobject( a, Pixmap );
+  if(b)
+    mask = get_gdkobject( b, Bitmap );
+  THIS->obj = GTK_OBJECT( gtk_pixmap_new( img, mask ) );
+  pgtk__init_this_object();
+  pop_n_elems(args);
+}
+
+FUNCTION(set, "function(object,object|void:object)")
+ARGS(GDK.Pixmap,GDK.Bitmap);
+NAME_ARGS(pixmap,mask);
+// Sets the GDK.Pixmap image and the optinal GDK.Bitmap mask
+{
+  struct object *a, *b;
+  GdkPixmap *img;
+  GdkBitmap *mask = NULL;
+  if(args == 2)
+    get_all_args("GDK.Pixmap->set", args, "%o%o", &a, &b);
+  else
+  {
+    get_all_args("GDK.Pixmap->set", args, "%o", &a);
+    b = 0;
+  }
+  img = get_gdkobject( a, Pixmap );
+  if(b)
+    mask = get_gdkobject( b, Bitmap );
+  /* TODO: Free refs for pixmap & mask! */
+  gtk_pixmap_set( GTK_PIXMAP(THIS->obj), img, mask );
+
+  RETURN_THIS();
+}
+
+CLASSMEMBER(build_insensitive, int);
+
+FUNCTION(get, "function(void:mapping)");
+// Returns ([ <br>
+//            "pixmap":pixmap, <br>
+//            "mask":mask,  <br>
+//            "pixmap_insensitive":insensitive version of the pixmap <br>
+//          ]) <br>
+{
+  pop_n_elems( args );
+
+
+  push_text( "pixmap" );
+  if( GTK_PIXMAP( THIS->obj )->pixmap )
+  {
+    gdk_pixmap_ref( GTK_PIXMAP( THIS->obj )->pixmap );
+    push_gdkobject( GTK_PIXMAP( THIS->obj )->pixmap, Pixmap );
+  }
+  else
+    push_int( 0 );
+
+  push_text( "mask" );
+  if( GTK_PIXMAP( THIS->obj )->mask )
+  {
+    gdk_pixmap_ref( GTK_PIXMAP( THIS->obj )->pixmap );
+    push_gdkobject( GTK_PIXMAP( THIS->obj )->mask, Bitmap );
+  }
+  else
+    push_int( 0 );
+
+  push_text( "pixmap_insensitive" );
+  if( GTK_PIXMAP( THIS->obj )->pixmap_insensitive )
+  {
+    gdk_pixmap_ref( GTK_PIXMAP( THIS->obj )->pixmap );
+    push_gdkobject( GTK_PIXMAP( THIS->obj )->pixmap_insensitive, Pixmap );
+  }
+  else
+    push_int( 0 );
+  f_aggregate_mapping( 6 );
+}
+
+COMPLEX_FUNCTION(set_build_insensitive, int);
+NAME_ARGS(buildp);
+// Set to TRUE if an extra pixmap should be automatically created to
+// use when the pixmap is insensitive.
+
+FUNCTION(set_pixmap_insensitive, "function(object:object)");
+ARGS(GDK.Pixmap);
+NAME_ARGS(insensitive_pixmap);
+RETURNS(GTK.Pixmap);
+// Set the pixmap to use when the pixmap is insensitive.
+{
+  struct object *o;
+  get_all_args( "set_pixmap_insensitive", args, "%o", &o );
+  if(!get_gdkobject( o, Pixmap ))
+    error("This is not a GDK.Pixmap\n");
+  if( GTK_PIXMAP( THIS->obj )->pixmap_insensitive != 
+      get_gdkobject( o, Pixmap ) )
+  {
+    gdk_pixmap_ref( get_gdkobject( o, Pixmap ) );
+    if(GTK_PIXMAP( THIS->obj )->pixmap_insensitive)
+      gdk_pixmap_unref( GTK_PIXMAP( THIS->obj )->pixmap_insensitive );
+    GTK_PIXMAP( THIS->obj )->pixmap_insensitive = get_gdkobject( o, Pixmap );
+  }
+  RETURN_THIS();
+}
diff --git a/src/post_modules/GTK/source/gtkplot.pre b/src/post_modules/GTK/source/gtkplot.pre
new file mode 100644
index 0000000000000000000000000000000000000000..79d9509dfd5d1910b77b82ddd407737df816666a
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkplot.pre
@@ -0,0 +1,412 @@
+COND_WIDGET(plot);
+ADD_INCLUDE(#include "gtkplot.h");
+ADD_INCLUDE(#include "gtkplotlayout.h");
+
+CONSTANT(GTK_PLOT_SHOW_LEFT_AXIS);
+CONSTANT(GTK_PLOT_SHOW_RIGHT_AXIS);
+CONSTANT(GTK_PLOT_SHOW_TOP_AXIS);
+CONSTANT(GTK_PLOT_SHOW_BOTTOM_AXIS);
+CONSTANT(GTK_PLOT_SHOW_V_GRID);
+CONSTANT(GTK_PLOT_SHOW_H_GRID);
+CONSTANT(GTK_PLOT_SHOW_X0);
+CONSTANT(GTK_PLOT_SHOW_Y0);
+
+
+CONSTANT(GTK_PLOT_SCALE_LINEAR);
+CONSTANT(GTK_PLOT_SCALE_LOG10);
+
+CONSTANT(GTK_PLOT_SYMBOL_NONE);
+CONSTANT(GTK_PLOT_SYMBOL_SQUARE);
+CONSTANT(GTK_PLOT_SYMBOL_CIRCLE);
+CONSTANT(GTK_PLOT_SYMBOL_UP_TRIANGLE);
+CONSTANT(GTK_PLOT_SYMBOL_DOWN_TRIANGLE);
+CONSTANT(GTK_PLOT_SYMBOL_DIAMOND);
+CONSTANT(GTK_PLOT_SYMBOL_BAR);
+CONSTANT(GTK_PLOT_SYMBOL_PLUS);
+CONSTANT(GTK_PLOT_SYMBOL_CROSS);
+CONSTANT(GTK_PLOT_SYMBOL_STAR);
+CONSTANT(GTK_PLOT_SYMBOL_IMPULSE);
+
+CONSTANT(GTK_PLOT_SYMBOL_EMPTY);
+CONSTANT(GTK_PLOT_SYMBOL_FILLED);
+CONSTANT(GTK_PLOT_SYMBOL_OPAQUE);
+
+CONSTANT(GTK_PLOT_LINE_NONE);
+CONSTANT(GTK_PLOT_LINE_FULL);
+CONSTANT(GTK_PLOT_LINE_DOTTED);
+CONSTANT(GTK_PLOT_LINE_DASHED);
+CONSTANT(GTK_PLOT_LINE_DOT_DASH);
+CONSTANT(GTK_PLOT_LINE_DOT_DOT_DASH);
+CONSTANT(GTK_PLOT_LINE_DOT_DASH_DASH);
+
+CONSTANT(GTK_PLOT_CONNECT_NONE);
+CONSTANT(GTK_PLOT_CONNECT_STRAIGHT);
+CONSTANT(GTK_PLOT_CONNECT_SPLINE);
+CONSTANT(GTK_PLOT_CONNECT_HV_STEP);
+CONSTANT(GTK_PLOT_CONNECT_VH_STEP);
+CONSTANT(GTK_PLOT_CONNECT_MIDDLE_STEP);
+
+CONSTANT(GTK_PLOT_LABEL_NONE);
+CONSTANT(GTK_PLOT_LABEL_LEFT);
+CONSTANT(GTK_PLOT_LABEL_RIGHT);
+CONSTANT(GTK_PLOT_LABEL_TOP);
+CONSTANT(GTK_PLOT_LABEL_BOTTOM);
+
+CONSTANT(GTK_PLOT_AXIS_LEFT);
+CONSTANT(GTK_PLOT_AXIS_RIGHT);
+CONSTANT(GTK_PLOT_AXIS_TOP);
+CONSTANT(GTK_PLOT_AXIS_BOTTOM);
+
+CONSTANT(GTK_PLOT_LABEL_FIXED);
+CONSTANT(GTK_PLOT_LABEL_EXP);
+
+
+CONSTANT(GTK_PLOT_TICKS_NONE);
+CONSTANT(GTK_PLOT_TICKS_LEFT);
+CONSTANT(GTK_PLOT_TICKS_RIGHT);
+CONSTANT(GTK_PLOT_TICKS_UP);
+CONSTANT(GTK_PLOT_TICKS_DOWN);
+
+
+PROGRAM(plot);
+#include "gtkplot.h"
+#include "gtkplotlayout.h"
+
+#define GTK_PLOT_DATASET(X) ((GtkPlotData *)X)
+#define GtkPlotDataset GtkPlotData
+
+static void push_gtk_plot_text( GtkPlotText *t )
+{
+  push_text("x");      push_int( t->x );
+  push_text("y");      push_int( t->y );
+  push_text("angle");  push_int( t->angle );
+  push_text("font");   push_gdkobject( t->font, Font );
+  push_text("color");  push_gdkobject( &t->color, Color );
+  f_aggregate_mapping( 10 );
+}
+
+static void push_gtk_plot_point( GtkPlotPoint *p )
+{
+  push_text( "x" ); push_float( p->x );
+  push_text( "y" ); push_float( p->y );
+  push_text( "xerr" ); push_float( p->xerr );
+  push_text( "yerr" ); push_float( p->yerr );
+  push_text( "deltax" ); push_float( p->deltax );
+  f_aggregate_mapping( 5 );
+}
+
+static void push_gtk_plot_line( GtkPlotLine *l )
+{
+  push_text( "line_style" ); push_int( l->line_style );
+  push_text( "line_width" ); push_int( l->line_width );
+  push_text("color");  push_gdkobject( &l->color, Color );
+  f_aggregate_mapping( 6 );
+}
+
+static void push_gtk_plot_symbol( GtkPlotSymbol *l )
+{
+  push_text( "symbol_type" ); push_int( l->symbol_type );
+  push_text( "symbol_style" ); push_int( l->symbol_style );
+  push_text( "size" );         push_int( l->size );
+  push_text( "line_width" );   push_int( l->line_width );
+  push_text("color");  push_gdkobject( &l->color, Color );
+  f_aggregate_mapping( 10 );
+}
+
+static void push_gtk_plot_axis( GtkPlotAxis *a )
+{
+  push_text( "title" ); push_text( a->title );
+  push_text( "title_attr" ); push_gtk_plot_text( &a->title_attr );
+  push_text( "title_visible" ); push_int( a->title_visible );
+  push_text( "orientation" ); push_int( a->orientation );
+  push_text( "scale_type" ); push_int( a->scale_type );
+  push_text( "scale_type" ); push_int( a->scale_type );
+  push_text( "line" ); push_gtk_plot_line( &a->line );
+  push_text( "min" ); push_float( a->min );
+  push_text( "max" ); push_float( a->max );
+  push_text( "major_ticks" ); push_float( a->major_ticks );
+  push_text( "minor_ticks" ); push_float( a->minor_ticks );
+  push_text( "ticks_length" ); push_int( a->ticks_length );
+  push_text( "ticks_width" ); push_int( a->ticks_width );
+  push_text( "label_attr" ); push_gtk_plot_text( &a->label_attr );
+  push_text( "label_precision" ); push_int( a->label_precision );
+  push_text( "label_style" ); push_int( a->label_style );
+  push_text( "label_mask" ); push_int( a->label_mask );
+  push_text( "ticks_mask" ); push_int( a->ticks_mask );
+  f_aggregate_mapping( 36 );
+}
+
+static void push_gtk_plot_data( GtkPlotData *d )
+{
+  int i;
+  push_text( "is_function" ); push_int( d->is_function );
+  push_text( "is_visible" );  push_int( d->is_visible );
+  push_text( "legend" );  push_text( d->legend );
+  push_text( "symbol" ); push_gtk_plot_symbol( &d->symbol );
+  push_text( "line" ); push_gtk_plot_line( &d->line );
+  push_text( "x" ); push_gtk_plot_line( &d->x );
+  push_text( "y" ); push_gtk_plot_line( &d->y );
+  push_text( "line_connector" ); push_int( d->line_connector );
+  push_text( "show_xerrbars"); push_int( d->show_xerrbars );
+  push_text( "show_yerrbars"); push_int( d->show_yerrbars );
+  push_text( "xerrbar_length"); push_int( d->xerrbar_length );
+  push_text( "yerrbar_length"); push_int( d->yerrbar_length );
+  if(!d->is_function)
+  {
+    push_text( "points" );
+    for(i=0; i<d->num_points; i++)
+      push_gtk_plot_point( d->points+i );
+    f_aggregate( d->num_points );
+  } else {
+    /*     push_text("function"); */
+    /*                            */
+  }
+  push_text("x_step"); push_int( d->x_step );
+}
+
+CLASSMEMBER(flags, int);
+CLASSMEMBER(x, float);
+CLASSMEMBER(y, float);
+CLASSMEMBER(width, float);
+CLASSMEMBER(height, float);
+
+CLASSMEMBER(xmin, float);
+CLASSMEMBER(ymin, float);
+CLASSMEMBER(xmax, float);
+CLASSMEMBER(ymax, float);
+CLASSMEMBER(xscale, float);
+CLASSMEMBER(yscale, float);
+
+CLASSMEMBER(legends_x, float);
+CLASSMEMBER(legends_y, float);
+CLASSMEMBER(legends_line_width, int);
+CLASSMEMBER(legends_shadow_width, int);
+CLASSMEMBER(show_legends, int);
+CLASSMEMBER(show_legends_border, int);
+CLASSMEMBER(show_legends_shadow, int);
+
+
+FUNCTION(get_bottom, "function(void:mapping)");
+{
+  push_gtk_plot_axis( &GTK_PLOT(THIS->obj)->bottom );
+}
+FUNCTION(get_top, "function(void:mapping)");
+{
+  push_gtk_plot_axis( &GTK_PLOT(THIS->obj)->top );
+}
+FUNCTION(get_left, "function(void:mapping)");
+{
+  push_gtk_plot_axis( &GTK_PLOT(THIS->obj)->left );
+}
+FUNCTION(get_right, "function(void:mapping)");
+{
+  push_gtk_plot_axis( &GTK_PLOT(THIS->obj)->right );
+}
+
+FUNCTION(get_major_vgrid, "function(void:mapping)");
+{
+  push_gtk_plot_line( &GTK_PLOT(THIS->obj)->major_vgrid );
+}
+
+FUNCTION(get_major_hgrid, "function(void:mapping)");
+{
+  push_gtk_plot_line( &GTK_PLOT(THIS->obj)->major_hgrid );
+}
+
+FUNCTION(get_minor_vgrid, "function(void:mapping)");
+{
+  push_gtk_plot_line( &GTK_PLOT(THIS->obj)->minor_vgrid );
+}
+
+FUNCTION(get_minor_hgrid, "function(void:mapping)");
+{
+  push_gtk_plot_line( &GTK_PLOT(THIS->obj)->minor_hgrid );
+}
+
+FUNCTION(get_x0_line, "function(void:mapping)");
+{
+  push_gtk_plot_line( &GTK_PLOT(THIS->obj)->x0_line );
+}
+
+FUNCTION(get_y0_line, "function(void:mapping)");
+{
+  push_gtk_plot_line( &GTK_PLOT(THIS->obj)->y0_line );
+}
+
+FUNCTION(get_legends_attr, "function(void:mapping)");
+{
+  push_gtk_plot_text( &GTK_PLOT(THIS->obj)->legends_attr );
+}
+
+
+COMPLEX_FUNCTION(create, ?GdkDrawable);
+COMPLEX_FUNCTION(set_drawable, GdkDrawable);
+COMPLEX_FUNCTION(move, float,float);
+COMPLEX_FUNCTION(resize, float,float);
+COMPLEX_FUNCTION(move_resize, float,float,float,float);
+COMPLEX_FUNCTION(set_range,float,float,float,float);
+NAME_ARGS(xmin,xmax,ymin,ymax);
+COMPLEX_FUNCTION(set_xscale, int);
+COMPLEX_FUNCTION(set_yscale, int);
+COMPLEX_FUNCTION(put_text, float,float,int,?GdkFont,*GdkColor,string);
+NAME_ARGS(x,y,angle,font,color,text);
+FUNCTION(get_axis, "function(int:mapping)");
+{
+  int ax;
+  get_all_args( "get_axis", args, "%d", &ax );
+  push_gtk_plot_axis( gtk_plot_get_axis( GTK_PLOT( THIS->obj ), ax) );
+}
+COMPLEX_FUNCTION(axis_set_title, int, string);
+NAME_ARGS(axis,title);
+COMPLEX_FUNCTION(axis_show_title, int);
+COMPLEX_FUNCTION(axis_hide_title, int);
+COMPLEX_FUNCTION(axis_move_title, int, int, int, int);
+NAME_ARGS(axis,angle,x,y);
+COMPLEX_FUNCTION(axis_set_attributes, int, int, *GdkColor);
+NAME_ARGS(axis,width,color);
+COMPLEX_FUNCTION(axis_set_ticks, int, float, float);
+NAME_ARGS(axis,major_tic,minor_tic);
+COMPLEX_FUNCTION(axis_set_ticks_length, int, int);
+NAME_ARGS(axis,length);
+COMPLEX_FUNCTION(axis_set_ticks_width, int, int);
+NAME_ARGS(axis,width);
+COMPLEX_FUNCTION(axis_show_ticks, int, int);
+NAME_ARGS(axis,mask);
+COMPLEX_FUNCTION(axis_labels_set_attributes, int, GdkFont, *GdkColor);
+NAME_ARGS(axis,font,color);
+COMPLEX_FUNCTION(axis_labels_set_numbers, int, int, int);
+NAME_ARGS(axis,style,precision);
+
+COMPLEX_FUNCTION(set_y0line_attributes, int, int, *GdkColor);
+NAME_ARGS(style,width,color);
+COMPLEX_FUNCTION(set_x0line_attributes, int, int, *GdkColor);
+NAME_ARGS(style,width,color);
+COMPLEX_FUNCTION(set_major_vgrid_attributes, int, int, *GdkColor);
+NAME_ARGS(style,width,color);
+COMPLEX_FUNCTION(set_major_hgrid_attributes, int, int, *GdkColor);
+NAME_ARGS(style,width,color);
+COMPLEX_FUNCTION(set_minor_vgrid_attributes, int, int, *GdkColor);
+NAME_ARGS(style,width,color);
+COMPLEX_FUNCTION(set_minor_hgrid_attributes, int, int, *GdkColor);
+NAME_ARGS(style,width,color);
+
+COMPLEX_FUNCTION(show_legends);
+COMPLEX_FUNCTION(hide_legends);
+COMPLEX_FUNCTION(show_legends_border, int, int);
+NAME_ARGS(show_shadow,shadow_width);
+COMPLEX_FUNCTION(hide_legends_border);
+COMPLEX_FUNCTION(legends_move, float,float);
+NAME_ARGS(x,y);
+COMPLEX_FUNCTION(legends_set_attributes, GdkFont, *GdkColor);
+NAME_ARGS(font,color);
+
+plot_dataset COMPLEX_FUNCTION(dataset_new);
+COMPLEX_FUNCTION(add_dataset, plot_dataset);
+
+/* static struct svalue *my_dup_svalue( struct svalue *s ) */
+/* { */
+/*   struct svalue *res; */
+/*   res = malloc(sizeof(struct svalue)); */
+/*   assign_svalue_no_free( res, s ); */
+/*   return res; */
+/* } */
+
+/* static void my_free_svalue( struct svalue *s ) */
+/* { */
+/*   free_svalue( s ); */
+/*   free( s ); */
+/* } */
+
+/* static gdouble my_generic_function_wrapper( float x, float *err ) */
+/* { */
+/*   if(err) *err = 0.0; */
+  
+/* } */
+
+/* FUNCTION(add_function, "function(function:object)"); */
+/* NAME_ARGS(f); */
+/* RETURNS(GTK.PlotData); */
+/* // f(x) -> y || ({ y,y_error }) */
+/* { */
+/*   GtkPlotData *d = gtk_plot_add_function( my_generic_function_wrapper ); */
+  
+/*   gtk_object_set_data_full(THIS->obj, "pike_method_function", */
+/*                              (void*)my_dup_svalue(sp-1), (void*)my_free_svalue); */
+/* } */
+
+
+PROGRAM(plot_dataset);
+#include "gtkplot.h"
+#include "gtkplotlayout.h"
+#define GTK_PLOT_DATASET(X) ((GtkPlotData *)X)
+#define GtkPlotDataset GtkPlotData
+
+
+COMPLEX_FUNCTION(set_symbol, int, int, int, int, *GdkColor);
+NAME_ARGS(type,style,size,line_width,color);
+COMPLEX_FUNCTION(set_connector, int);
+NAME_ARGS(type);
+
+COMPLEX_FUNCTION(set_line_attributes, int, int, *GdkColor);
+NAME_ARGS(style,width,color);
+
+COMPLEX_FUNCTION(set_xy_attributes, int, int, *GdkColor);
+NAME_ARGS(style,width,color);
+
+COMPLEX_FUNCTION(show_xerrbars);
+COMPLEX_FUNCTION(show_yerrbars);
+COMPLEX_FUNCTION(hide_xerrbars);
+COMPLEX_FUNCTION(hide_yerrbars);
+COMPLEX_FUNCTION(set_legend, string);
+#define gtk_plot_dataset_show gtk_plot_show_dataset
+COMPLEX_FUNCTION(show);
+#define gtk_plot_dataset_hide gtk_plot_hide_dataset
+COMPLEX_FUNCTION(hide);
+
+FUNCTION(set_points, "function(array(array):object)");
+// ({ ({ x,y,[xerr[,yerr[,deltax]]] }), ... })
+// all numbers are floats.
+{
+  struct array *a;
+  GtkPlotPoint *points;
+  int npoints;
+  int i;
+  get_all_args( "set_points", args, "%a", &a );
+  points = gtk_plot_dataset_get_points( GTK_PLOT_DATASET(THIS->obj), &npoints );
+  if(points) free(points);
+  points = malloc( sizeof( GtkPlotPoint ) * a->size );
+  MEMSET(points, 0, sizeof( GtkPlotPoint ) * a->size);
+  for(i=0; i<a->size; i++)
+  {
+    points[i].x=points[i].y=points[i].xerr=points[i].yerr=points[i].deltax=0.0;
+    if(a->item[i].type == T_ARRAY)
+    {
+      struct array *q;
+      q = a->item[i].u.array;
+      switch(q->size)
+      {
+       case 5:
+         points[i].deltax = q->item[3].u.float_number;
+       case 4:
+         points[i].yerr = q->item[3].u.float_number;
+       case 3:
+         points[i].xerr = q->item[2].u.float_number;
+       case 2:
+         points[i].y = q->item[1].u.float_number;
+       case 1:
+         points[i].x = q->item[0].u.float_number;
+      }
+    }
+  }
+}
+
+PROGRAM(plot_layout);
+#include "gtkplot.h"
+#include "gtkplotlayout.h"
+INHERIT(layout);
+COMPLEX_FUNCTION(create,int,int);
+NAME_ARGS(width,height);
+COMPLEX_FUNCTION(add_plot, plot,int,int);
+NAME_ARGS(plot,x,y);
+
+END_COND_WIDGET(plot);
diff --git a/src/post_modules/GTK/source/gtkplug.pre b/src/post_modules/GTK/source/gtkplug.pre
new file mode 100644
index 0000000000000000000000000000000000000000..9bd9a73c253b48e7c60f7fd482942a4661760e1c
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkplug.pre
@@ -0,0 +1,17 @@
+PROGRAM(plug);
+// Together with W(Socket), GTK.Plug provides the ability to embed
+// widgets from one process into another process in a fashion that is
+// transparent to the user. One process creates a W(Socket) widget
+// and, passes the XID of that widgets window to the other process,
+// which then creates a GTK.Plug window with that XID. Any widgets
+// contained in the GTK.Plug then will appear inside the first
+// applications window.
+
+INHERIT(window);
+COMPLEX_FUNCTION(create, int);
+NAME_ARGS(socket_id);
+// Create a new plug, the socket_id is the window into which this plug
+// will be plugged.
+CLASSMEMBER(same_app,int);
+// returns 1 if the socket the plug is connected to is in this
+// application.
diff --git a/src/post_modules/GTK/source/gtkprogress.pre b/src/post_modules/GTK/source/gtkprogress.pre
new file mode 100644
index 0000000000000000000000000000000000000000..fbc0ce4bd1a8d43dbdf9a7e3469c3f76afd100f8
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkprogress.pre
@@ -0,0 +1,73 @@
+PROGRAM(progress);
+INHERIT(widget);
+COMPLEX_FUNCTION(set_show_text, int);
+NAME_ARGS(textp);
+// If true, write a text in the progress bar.
+COMPLEX_FUNCTION(set_text_alignment, float, float);
+NAME_ARGS(xalign, yalign);
+// The location for the text in the progress bar.<br>
+// xalign is between 0.0 (leftmost) and 1.0 (rightmost)<br>
+// yalign is between 0.0 (topmost) and 1.0 (bottommost)<br>
+// <p>
+// Default is xalign == yalign == 0.5
+COMPLEX_FUNCTION(set_format_string, string);
+NAME_ARGS(format);
+// 
+// More or less like sprintf.<p>
+// %[field width][character]<p>
+// 0<=width<=2<p>
+// Supported characters:
+// <dl><dt><dd><pre>
+// %: Insert a %<br>
+// p or P: The percentage completed, with 'digits' number of decimals
+// v or V: The actual value, with digits decimals.
+// l or L: The lower value (from the adjustment)
+// u or U: The higer value (from the adjustment)
+// %: Insert a %
+// </pre></dl>The default format is '%P%%'
+COMPLEX_FUNCTION(set_adjustment, Adjustment);
+NAME_ARGS(adjustment);
+// Sets the adjustment to use. See the adjustment documentation for more info
+COMPLEX_FUNCTION(configure, float, float, float);
+NAME_ARGS(value, min, max);
+// Sets the current value, the minimum value and the maximum value.
+// The default min and max are 0.0 and 1.0 respectively.
+COMPLEX_FUNCTION(set_percentage, float);
+NAME_ARGS(pct);
+// Sets the value (between 0.0 and 1.0). Uses the min and max values.
+COMPLEX_FUNCTION(set_activity_mode, int);
+NAME_ARGS(modep);
+// As well as indicating the amount of progress that has occured, the
+// progress bar may be set to just indicate that there is some
+// activity. This can be useful in situations where progress cannot be
+// measured against a value range.<p>
+// Mode is:<br>
+// 1: active<br>
+// 0: inactive<br>
+COMPLEX_FUNCTION(set_value,float);
+NAME_ARGS(value);
+// Set the value.
+float COMPLEX_FUNCTION(get_value);
+// Return the current value
+string COMPLEX_FUNCTION(get_current_text);
+// Return the current text (see set_format_string)
+string COMPLEX_FUNCTION(get_text_from_value, float);
+NAME_ARGS(value);
+// Formats 'value' and returns it as a text.
+float COMPLEX_FUNCTION(get_current_percentage);
+// Returns a float between 0.0 and 1.0
+float COMPLEX_FUNCTION(get_percentage_from_value, float);
+NAME_ARGS(value);
+// Returns a float between 0.0 and 1.0
+/* SUBWIDGET(adjustment, adjustment); */
+
+CLASSMEMBER(show_text, int);
+// 1 if the text will be shown
+CLASSMEMBER(activity_mode, int);
+// The currently set activity mode.
+CLASSMEMBER(x_align, float);
+// The text alignment, 0.0 is leftmost, 1.0 is rightmost
+CLASSMEMBER(y_align, float);
+// The text alignment, 0.0 is topmost, 1.0 is bottommost
+CLASSMEMBER(format, string);
+// The format used to convert the value to a the text
diff --git a/src/post_modules/GTK/source/gtkprogressbar.pre b/src/post_modules/GTK/source/gtkprogressbar.pre
new file mode 100644
index 0000000000000000000000000000000000000000..ec6a2e214df504a38ee3e2b2b4658c5bf940123a
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkprogressbar.pre
@@ -0,0 +1,51 @@
+PROGRAM(progress_bar);
+// A simple progress bar. Useful when you are doing things that take a long
+// time. Try to always have an 'abort' button whenever it makes sence.
+// IMG: GTK.ProgressBar()->update(0.1)
+// IMG: GTK.ProgressBar()->set_show_text(1)->update(0.3)
+// IMG: GTK.ProgressBar()->update(0.6)
+// IMG: GTK.ProgressBar()->update(1.0)
+INHERIT(progress);
+COMPLEX_FUNCTION(create);
+// Create a new progress bar.
+// The default values are:<br>
+// Min 0.0, max 1.0, current 0.0<br>
+COMPLEX_FUNCTION(update, float);
+NAME_ARGS(fraction);
+// 0.0 is the minimum value, 1.0 is the maximum value.
+COMPLEX_FUNCTION(set_bar_style, int);
+NAME_ARGS(style);
+// One of GTK.ProgressContinuous or GTK.ProgressDiscrete
+COMPLEX_FUNCTION(set_discrete_blocks, int);
+NAME_ARGS(blocks);
+// The number of discrete blocks in the progress bar
+COMPLEX_FUNCTION(set_activity_step, int);
+NAME_ARGS(stepp);
+// Include activity blocks (empty gaps in the progressbar, ala windows 98)
+COMPLEX_FUNCTION(set_activity_blocks, int);
+NAME_ARGS(blocks);
+// The number of activity blocks
+COMPLEX_FUNCTION(set_orientation, int);
+NAME_ARGS(style);
+// One of 
+// GTK.ProgressLeftToRight, GTK.ProgressRightToLeft,
+// GTK.ProgressBottomToTop or GTK.ProgressTopToBottom
+
+CLASSMEMBER(activity_pos, int);
+// The position of the progress meter in pixels.
+CLASSMEMBER(activity_step, int);
+// The step size of the activity indicator in pixels.
+CLASSMEMBER(activity_blocks, int);
+// The number of blocks that are set.
+CLASSMEMBER(activity_dir, int);
+// The current direction of the progress meter. 1 is forward and 0 is
+// backwards. Usefull if you for some strange reason would like to
+// know in what direction the activity indicator is swinging right
+// now...
+CLASSMEMBER(blocks, int);
+// The total number of blocks.
+CLASSMEMBER(orientation, int);
+// The current orientation. GTK_PROGRESS_LEFT_TO_RIGHT, GTK_PROGRESS_RIGHT_TO_LEFT,
+// GTK_PROGRESS_BOTTOM_TO_TOP or GTK_PROGRESS_TOP_TO_BOTTOM.
+CLASSMEMBER(bar_style, int);
+// The progress bar style. GTK_PROGRESS_CONTINUOUS or GTK_PROGRESS_DISCRETE.
diff --git a/src/post_modules/GTK/source/gtkradiobutton.pre b/src/post_modules/GTK/source/gtkradiobutton.pre
new file mode 100644
index 0000000000000000000000000000000000000000..91df965c09083812fd6e42fcaa96dec801985735
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkradiobutton.pre
@@ -0,0 +1,57 @@
+PROGRAM(radio_button);
+// Radio buttons are similar to check buttons except they are grouped
+// so that only one may be selected/depressed at a time. This is good
+// for places in your application where you need to select from a
+// short list of options.  <p> To connect the buttons, use another
+// button in the desired group as the second argument to
+// GTK.RadioButton(). 
+// IMG: GTK.Radio_button("Button");
+INHERIT(check_button);
+FUNCTION(create, "function(string|void,object|void:void)")
+NAME_ARGS(title,groupmember);
+//  Normal creation:<p>
+// object GTK.RadioButton(string title) - First button (with label)<br>
+// object GTK.RadioButton()->add(widget) - First button (with widget)<br>
+// object GTK.RadioButton(title, another_radio_button) - Second to n:th button (with title)<br>
+// object GTK.RadioButton(0,another_radio_button)->add(widget) - Second to n:th button (with widget)<br>
+{
+  GSList *mylist = NULL;
+  gchar *label=NULL;
+  struct object *o=NULL;
+  if(args)
+  {
+    if(sp[-args].type == T_STRING)
+      label = (gchar *)sp[-args].u.string->str;
+    if(args==2 && (sp[-1].type == T_OBJECT))
+	o = sp[-1].u.object;
+  }
+
+  if(THIS->obj) error("GTK.RadioButton->create() can only be called once.\n");
+
+  if(o) 
+    mylist=gtk_radio_button_group(GTK_RADIO_BUTTON(get_gtkobject(o)));
+
+  if(label)
+    THIS->obj=GTK_OBJECT(gtk_radio_button_new_with_label(mylist,label));
+  else
+    THIS->obj=GTK_OBJECT(gtk_radio_button_new(mylist));
+  pgtk__init_this_object();
+}
+
+FUNCTION(set_group, "function(object:object)")
+NAME_ARGS(groupmember);
+// the argument is another radio button to whose group this button
+// should be added to. It is prefereable to use the second argument to
+// the constructor instead, but if you for some reason want to move
+// the button to another group, use this function.
+{
+  struct object *o=NULL;
+  GSList *mylist;
+  get_all_args("set_group", args, "%o", &o );
+  
+  mylist = gtk_radio_button_group( GTK_RADIO_BUTTON( get_gtkobject( o ) ));
+  gtk_radio_button_set_group( GTK_RADIO_BUTTON( THIS->obj ), mylist );
+  RETURN_THIS();
+}
+
+/* TODO: group, g_list of members */
diff --git a/src/post_modules/GTK/source/gtkradiomenuitem.pre b/src/post_modules/GTK/source/gtkradiomenuitem.pre
new file mode 100644
index 0000000000000000000000000000000000000000..4ccca62a8d92bcefc072065839089f9c002cff78
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkradiomenuitem.pre
@@ -0,0 +1,49 @@
+PROGRAM(radio_menu_item);
+// Exactly like W(RadioButton), but it is an menu item.
+// IMG: GTK.RadioMenuItem("Menu item")
+INHERIT(menu_item);
+FUNCTION(create, "function(string|void,object|void:void)")
+NAME_ARGS(title,groupmember);
+// object GTK.RadioMenuItem(string title) - First button (with label)<br>
+// object GTK.RadioMenuItem()->add(widget) - First button (with widget)<br>
+// object GTK.RadioMenuItem(title, another_radio_button) - Second to n:th button (with title)<br>
+// object GTK.RadioMenuItem(0,another_radio_button)->add(widget) - Second to n:th button (with widget)<br>
+{
+  GSList *mylist = NULL;
+  gchar *label=NULL;
+  struct object *o=NULL;
+  if(args)
+  {
+    if(sp[-args].type == T_STRING)
+      label = (gchar *)sp[-args].u.string->str;
+    if(args==2 && (sp[-1].type == T_OBJECT))
+	o = sp[-1].u.object;
+  }
+
+  if(THIS->obj) error("GTK.Radio_group->create() can only be called once.\n");
+  if(o) mylist=gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(get_gtkobject(o)));
+
+  if(label)
+    THIS->obj=GTK_OBJECT(gtk_radio_menu_item_new_with_label(mylist,label));
+  else
+    THIS->obj=GTK_OBJECT(gtk_radio_menu_item_new(mylist));
+  pop_n_elems(args);
+  pgtk__init_this_object();
+}
+
+FUNCTION(set_group, "function(object:object)")
+NAME_ARGS(groupmember);
+// the argument is another radio menu item to whose group this button
+// should be added to. It is prefereable to use the second argument to
+// the constructor instead, but if you for some reason want to move
+// the button to another group, use this function.
+{
+  struct object *o;
+  GSList *mylist;
+  get_all_args("set_group", args, "%o", &o );
+  mylist=gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(get_gtkobject(o)));
+  gtk_radio_menu_item_set_group( GTK_RADIO_MENU_ITEM( THIS->obj ), mylist );
+  RETURN_THIS();
+}
+
+/* TODO: group, g_list of members */
diff --git a/src/post_modules/GTK/source/gtkrange.pre b/src/post_modules/GTK/source/gtkrange.pre
new file mode 100644
index 0000000000000000000000000000000000000000..80361218b5a31375dd94790714fbdf9e1e5afdd3
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkrange.pre
@@ -0,0 +1,107 @@
+PROGRAM(range);
+
+
+// The category of range widgets includes the ubiquitous scrollbar
+// widget and the less common "scale" widget. Though these two types
+// of widgets are generally used for different purposes, they are
+// quite similar in function and implementation. All range widgets
+// share a set of common graphic elements, each of which has its own X
+// window and receives events. They all contain a "trough" and a
+// "slider" (what is sometimes called a "thumbwheel" in other GUI
+// environments). Dragging the slider with the pointer moves it back
+// and forth within the trough, while clicking in the trough advances
+// the slider towards the location of the click, either completely, or
+// by a designated amount, depending on which mouse button is used.
+// <p>
+// As mentioned in the W(Adjustments) page, all range widgets are
+// associated with an adjustment object, from which they calculate the
+// length of the slider and its position within the trough. When the
+// user manipulates the slider, the range widget will change the value
+// of the adjustment.
+
+// <p>
+
+// All of the GTK range widgets react to mouse clicks in more or less
+// the same way. Clicking button-1 in the trough will cause its
+// adjustment's page_increment to be added or subtracted from its
+// value, and the slider to be moved accordingly. Clicking mouse
+// button-2 in the trough will jump the slider to the point at which
+// the button was clicked. Clicking any button on a scrollbar's arrows
+// will cause its adjustment's value to change step_increment at a
+// time.
+
+// <p>
+
+// It may take a little while to get used to, but by default,
+// scrollbars as well as scale widgets can take the keyboard focus in
+// GTK. If you think your users will find this too confusing, you can
+// always disable this by unsetting the GTK.CanFocus flag on the
+// scrollbar, like this:
+
+// <p>
+
+// <tt>scrollbar->unset_flag( GTK.CanFocus );</tt>
+
+// <p>
+
+// The key bindings (which are, of course, only active when the widget
+// has focus) are slightly different between horizontal and vertical
+// range widgets, for obvious reasons. They are also not quite the
+// same for scale widgets as they are for scrollbars, for somewhat
+// less obvious reasons (possibly to avoid confusion between the keys
+// for horizontal and vertical scrollbars in scrolled windows, where
+// both operate on the same area).
+
+// <p>
+
+INHERIT(widget);
+COMPLEX_FUNCTION(set_update_policy, int);
+NAME_ARGS(when);
+// The "update policy" of a range widget defines at what points during
+// user interaction it will change the value field of its Adjustment
+// and emit the "value_changed" signal on this Adjustment. The update
+// policies are:
+// <dl>
+// <dt>GTK.UpdatePolicyContinuous 
+// <dd>This is the default. The "value_changed" signal is emitted
+// continuously, i.e., whenever the slider is moved by even the
+// tiniest amount.
+// <dt>GTK.UpdatePolicyDiscontinuous 
+// <dd> The "value_changed" signal is only emitted once the slider has
+// stopped moving and the user has released the mouse button.
+// <dt>GTK.UpdatePolicyDelayed
+// <dd>The "value_changed" signal is emitted when the user releases
+// the mouse button, or if the slider stops moving for a short period
+// of time.
+// </dl>
+COMPLEX_FUNCTION(set_adjustment, adjustment);
+NAME_ARGS(pos);
+// set_adjustment() does absolutely nothing if you pass it the
+// adjustment that range is already using, regardless of whether you
+// changed any of its fields or not. If you pass it a new Adjustment,
+// it will unreference the old one if it exists (possibly destroying
+// it), connect the appropriate signals to the new one, and call the
+// private function gtk_range_adjustment_changed(), which will (or at
+// least, is supposed to...) recalculate the size and/or position of
+// the slider and redraw if necessary.
+SIMPLE_FUNCTION(slider_update);
+// Update the slider values.
+
+CLASSMEMBER(x_click_point,int);
+CLASSMEMBER(y_click_point,int);
+
+CLASSMEMBER(button, int);
+CLASSMEMBER(digits, int);
+CLASSMEMBER(policy, int);
+CLASSMEMBER(scroll_type, int);
+CLASSMEMBER(in_child, int);
+CLASSMEMBER(click_child, int);
+CLASSMEMBER(need_timer, int);
+CLASSMEMBER(timer, int);
+
+CLASSMEMBER(old_value, float);
+CLASSMEMBER(old_lower, float);
+CLASSMEMBER(old_upper, float);
+CLASSMEMBER(old_page_size, float);
+
+SUBWIDGET(adjustment,adjustment);
diff --git a/src/post_modules/GTK/source/gtkruler.pre b/src/post_modules/GTK/source/gtkruler.pre
new file mode 100644
index 0000000000000000000000000000000000000000..d0bd430fe31f0b3b39fe6c23e549fee8f11b9d04
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkruler.pre
@@ -0,0 +1,31 @@
+PROGRAM(ruler);
+// Ruler widgets are used to indicate the location of the mouse
+// pointer in a given window. A window can have a vertical ruler
+// spanning across the width and a horizontal ruler spanning down
+// the height. A small triangular indicator on the ruler shows the
+// exact location of the pointer relative to the ruler.
+
+// <p>
+
+INHERIT(widget);
+COMPLEX_FUNCTION(set_metric, int);
+NAME_ARGS(unit);
+// Either GTK.Pixels, GTK.Centimers or GTK.Inches<p>
+// The default measure is GTK.Pixels
+COMPLEX_FUNCTION(set_range, float,float,float,float);
+NAME_ARGS(lower,upper,position,max_size);
+// The lower and upper arguments define the extent of the ruler, and
+// max_size is the largest possible number that will be displayed.
+// Position defines the initial position of the pointer indicator within the ruler. 
+SIMPLE_FUNCTION(draw_ticks);
+// draw the ticks
+SIMPLE_FUNCTION(draw_pos);
+// draw the position
+CLASSMEMBER(lower, float);
+// The currently defined lower extent of the ruler.
+CLASSMEMBER(upper, float);
+// The currently defined upper extent of the ruler.
+CLASSMEMBER(position, float);
+// The currently defined initial position of the pointer indicator within the ruler.
+CLASSMEMBER(max_size, float);
+// The currently defined max_size of the ruler.
diff --git a/src/post_modules/GTK/source/gtkscale.pre b/src/post_modules/GTK/source/gtkscale.pre
new file mode 100644
index 0000000000000000000000000000000000000000..604c32ff0ea5b904feb64fbca516deb66cc583cf
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkscale.pre
@@ -0,0 +1,26 @@
+PROGRAM(scale);
+// The GTK.Scale widget is an abstract class, used only for deriving
+// the subclasses GTK.Hscale and GTK.Vscale.
+// <p>
+// See W(Range) for generic range documentation
+// <p>
+INHERIT(range);
+COMPLEX_FUNCTION(set_digits, int);
+NAME_ARGS(precision);
+// Sets the number of decimal places that are displayed in the value.
+COMPLEX_FUNCTION(set_draw_value, int);
+NAME_ARGS(drawp);
+//  Specifies whether the current value is displayed as a string next
+//  to the slider.
+COMPLEX_FUNCTION(set_value_pos, int);
+NAME_ARGS(where);
+// Sets the position in which the current value is displayed. One of
+// CONST(GTK_POS)
+int COMPLEX_FUNCTION(get_value_width);
+// An internal function used to get the maximum width needed to
+// display the value string. Not normaly used by applications.
+CLASSMEMBER(draw_value, int);
+// non-zero if the scale's current value is displayed next to the slider.
+CLASSMEMBER(value_pos, int);
+// The position in which the textual value is displayed, selected from
+// CONST(GTK_POS)
diff --git a/src/post_modules/GTK/source/gtkscrollbar.pre b/src/post_modules/GTK/source/gtkscrollbar.pre
new file mode 100644
index 0000000000000000000000000000000000000000..a8baff1f96907d56542ece1a6f644f5fecc5d73f
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkscrollbar.pre
@@ -0,0 +1,8 @@
+PROGRAM(scrollbar);
+//  These are your standard, run-of-the-mill scrollbars. These should
+//  be used only for scrolling some other widget, such as a list, a
+//  text box, or a viewport (and it's generally easier to use the
+//  scrolled window widget in most cases). For other purposes, you
+//  should use scale widgets, as they are friendlier and more
+//  featureful.
+INHERIT(range);
diff --git a/src/post_modules/GTK/source/gtkscrolledwindow.pre b/src/post_modules/GTK/source/gtkscrolledwindow.pre
new file mode 100644
index 0000000000000000000000000000000000000000..44e7f4c6c9f6e784bfd1012666d540d22614170a
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkscrolledwindow.pre
@@ -0,0 +1,75 @@
+PROGRAM(scrolled_window);
+// Scrolled windows are used to create a scrollable area with another
+// widget inside it. You may insert any type of widget into a scrolled
+// window, and it will be accessible regardless of the size by using
+// the scrollbars.
+// <p>
+// IMG: GTK.ScrolledWindow(GTK.Adjustment(),GTK.Adjustment())->add(GTK.Label("A small label"))->set_usize(100,80)->set_policy(GTK.POLICY_AUTOMATIC,GTK.POLICY_AUTOMATIC)
+// IMG: GTK.ScrolledWindow(GTK.Adjustment(),GTK.Adjustment())->add(GTK.Label("A small label"))->set_usize(70,80)->set_policy(GTK.POLICY_AUTOMATIC,GTK.POLICY_AUTOMATIC)
+// IMG: GTK.ScrolledWindow(GTK.Adjustment(),GTK.Adjustment())->add(GTK.Label("A small label"))->set_usize(80,80)
+// IMG: GTK.ScrolledWindow(GTK.Adjustment(),GTK.Adjustment())->add(GTK.Label("A very huge label")->set_usize(700,700))->set_usize(80,80)
+INHERIT(window);
+COMPLEX_FUNCTION(create, ?adjustment, ?adjustment);
+NAME_ARGS(hadjustment,vadjustments);
+// The two adjustments are most commonly set to 0.
+COMPLEX_FUNCTION(set_hadjustment, adjustment);
+NAME_ARGS(hadjustment);
+// Set the horizontal adjustment object
+COMPLEX_FUNCTION(set_vadjustment, adjustment);
+NAME_ARGS(vadjustment);
+// Set the vertical adjustment object
+SUBWIDGET(hscrollbar, hscrollbar);
+// The horizontal scrollbar
+SUBWIDGET(vscrollbar, vscrollbar);
+// The vertical scrollbar
+COMPLEX_FUNCTION(set_policy, int, int);
+NAME_ARGS(xpolicy,ypolicy);
+// vertical and horiz policy. Both are one of CONST(GTK_POLICY)
+FUNCTION(add, "function(object:object)");
+ARGS(GTK.Widget);
+NAME_ARGS(victim);
+// Add a widget to this container.
+// This is equivalent to the 
+// C-GTK function gtk_scrolled_window_add_with_viewport or 
+// gtk_container_add, depeneding on whether or not the child supports
+// the set_scroll_adjustments signal.
+// <p>
+// What this means in practice is that you do not have to care about
+// this at all, it's all handled automatically.
+{
+  GtkWidget *victim;
+  struct object *o;
+
+  get_all_args( "add", args, "%o", &o );
+  victim = GTK_WIDGET( get_gtkobject( o ) );
+  if(!(GTK_WIDGET_CLASS(GTK_OBJECT(victim)->klass)->
+       set_scroll_adjustments_signal))
+    gtk_scrolled_window_add_with_viewport(GTK_SCROLLED_WINDOW(THIS->obj),
+                                          victim);
+  else
+    gtk_container_add( GTK_CONTAINER( THIS->obj ), victim );
+
+  RETURN_THIS();
+}
+
+COMPLEX_FUNCTION(set_placement, int);
+NAME_ARGS(window_corner_placement);
+// The location of the window relative to the scrollbars.
+// One of CONST(GTK_CORNER_)
+
+adjustment COMPLEX_FUNCTION(get_hadjustment);
+// Return the horizontal adjustment used to scroll the window
+adjustment COMPLEX_FUNCTION(get_vadjustment);
+// Return the vertical adjustment used to scroll the window
+
+CLASSMEMBER(hscrollbar_policy, int);
+// One of CONST(GTK_POLICY_)
+CLASSMEMBER(vscrollbar_policy, int);
+// One of CONST(GTK_POLICY_)
+CLASSMEMBER(hscrollbar_visible, int);
+// 1 if the horizontal scrollbar is currently visible
+CLASSMEMBER(vscrollbar_visible, int);
+// 1 if the vertical scrollbar is currently visible
+CLASSMEMBER(window_placement, int);
+// The location of the window relative to the scrollbars.
+// One of CONST(GTK_CORNER_)
diff --git a/src/post_modules/GTK/source/gtkselectiondata.pre b/src/post_modules/GTK/source/gtkselectiondata.pre
new file mode 100644
index 0000000000000000000000000000000000000000..a6ed64c615589b3511136c6b7741173e92b7f5fe
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkselectiondata.pre
@@ -0,0 +1,90 @@
+PROGRAM(selection_data);
+// The data associated with a selection.
+/* do not... INHERIT(data); */
+
+FUNCTION(data, "function(void:string)");
+// Returns the selection in the data.
+// The return value is always a string, but the width can vary (8, 16
+// or 32 bits per character).
+{
+  int length = ((GtkSelectionData *)THIS->obj)->length;
+  pop_n_elems( args );
+  if(length < 0)
+  {
+    push_int(0);
+    return;
+  }
+  switch( ((GtkSelectionData *)THIS->obj)->format )
+  {
+   case 8:
+     push_string( make_shared_binary_string((void *)((GtkSelectionData *)THIS->obj)
+                                            ->data, length ) );
+     break;
+   case 16:
+     length /= 2;
+     push_string( make_shared_binary_string1((void *)((GtkSelectionData *)THIS->obj)
+                                             ->data, length ) );
+     break;
+   case 32:
+     length /= 4;
+     push_string( make_shared_binary_string2((void *)((GtkSelectionData *)THIS->obj)
+                                             ->data, length ) );
+     break;
+  }
+}
+
+FUNCTION(format, "function(void:int)");
+// Returns the selction format.<br>
+// The format is the number of bits per character.
+{
+  pop_n_elems( args );
+  push_int( ((GtkSelectionData *)THIS->obj)->format );
+}
+
+FUNCTION(length, "function(void:int)");
+// Return the size of the selection data, in bytes.
+// <p>
+// The size of the data in characters (as returned by data()) is not
+// nessasarily the same.
+{
+  pop_n_elems( args );
+  push_int( ((GtkSelectionData *)THIS->obj)->length );
+}
+
+FUNCTION(set, "function(string:object)");
+NAME_ARGS(data);
+//  Store new data into a GtkSelectionData object. Should _only_ by
+//  called from a selection handler callback.
+
+{
+  struct pike_string *s;
+  get_all_args( "set", args, "%W", &s );
+  gtk_selection_data_set( ((GtkSelectionData *)THIS->obj),
+                          ((GtkSelectionData *)THIS->obj)->target,
+                          8<<s->size_shift,
+                          s->str,
+                          (s->len * 1<<s->size_shift) );
+  RETURN_THIS();
+}
+
+
+#define RETURN_GDKATOM(X) pop_n_elems(args); push_pgdkobject( ((void *)((GtkSelectionData *)THIS->obj)->X), pgtk_Gdk_Atom_program );
+
+
+FUNCTION(target, "function(void:object)");
+// The target, as a GDK(Atom).
+{
+  RETURN_GDKATOM( target );
+}
+
+FUNCTION(type, "function(void:object)");
+// The selection type, as a GDK(Atom).
+{
+  RETURN_GDKATOM( type );
+}
+
+FUNCTION(selection, "function(void:object)");
+// The selection id, as a GDK(Atom).
+{
+  RETURN_GDKATOM( selection );
+}
diff --git a/src/post_modules/GTK/source/gtkseparator.pre b/src/post_modules/GTK/source/gtkseparator.pre
new file mode 100644
index 0000000000000000000000000000000000000000..ee46cc23b2e9bdb92f97ec9d293394d3240c71c6
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkseparator.pre
@@ -0,0 +1,3 @@
+PROGRAM(separator);
+// A generic separator. Basicaly a line, like &lt;hr&gt; in HTML.
+INHERIT(widget);
diff --git a/src/post_modules/GTK/source/gtksheet.pre b/src/post_modules/GTK/source/gtksheet.pre
new file mode 100644
index 0000000000000000000000000000000000000000..e8c377e7d4cfec9c74da82116ef21051b100dc23
--- /dev/null
+++ b/src/post_modules/GTK/source/gtksheet.pre
@@ -0,0 +1,374 @@
+COND_WIDGET(sheet);
+ADD_INCLUDE(#include <gtksheet.h>);
+ADD_INCLUDE(#include <gtksheetentry.h>);
+CONSTANT(GTK_SHEET_FOREGROUND);
+CONSTANT(GTK_SHEET_BACKGROUND);
+CONSTANT(GTK_SHEET_FONT);
+CONSTANT(GTK_SHEET_JUSTIFICATION);
+CONSTANT(GTK_SHEET_BORDER);
+CONSTANT(GTK_SHEET_BORDER_COLOR);
+CONSTANT(GTK_SHEET_IS_EDITABLE);
+CONSTANT(GTK_SHEET_IS_VISIBLE);
+CONSTANT(GTK_SHEET_NORMAL);
+CONSTANT(GTK_SHEET_ROW_SELECTED);
+CONSTANT(GTK_SHEET_COLUMN_SELECTED);
+CONSTANT(GTK_SHEET_RANGE_SELECTED);
+CONSTANT(GTK_SHEET_IS_LOCKED);
+CONSTANT(GTK_SHEET_IS_FROZEN);
+CONSTANT(GTK_SHEET_IN_XDRAG);
+CONSTANT(GTK_SHEET_IN_YDRAG);
+CONSTANT(GTK_SHEET_IN_DRAG);
+CONSTANT(GTK_SHEET_IN_SELECTION);
+CONSTANT(GTK_SHEET_IN_RESIZE);
+CONSTANT(GTK_SHEET_IN_CLIP);
+CONSTANT(GTK_SHEET_ROW_FROZEN);
+CONSTANT(GTK_SHEET_COLUMN_FROZEN);
+CONSTANT(GTK_SHEET_AUTORESIZE);
+CONSTANT(GTK_SHEET_ADJUST_TEXT);
+CONSTANT(GTK_SHEET_ROW_TITLES_VISIBLE);
+CONSTANT(GTK_SHEET_COL_TITLES_VISIBLE);
+CONSTANT(GTK_SHEET_AUTO_SCROLL);
+
+PROGRAM(shentry);
+#include <gtksheetentry.h>
+INHERIT(entry);
+FUNCTION(create, "function(void|int:void)");
+NAME_ARGS(max_width);
+{
+  if(args)
+    THIS->obj = GTK_OBJECT(gtk_shentry_new_with_max_length( sp[-1].u.integer ));
+  else
+    THIS->obj = GTK_OBJECT(gtk_shentry_new(  ));
+}
+COMPLEX_FUNCTION(set_text, string, int );
+NAME_ARGS(text,justifictation);
+COMPLEX_FUNCTION(set_justification, int );
+NAME_ARGS(justifictation);
+
+PROGRAM(sheet);
+#include <gtksheet.h>
+// IMG: GTK.Sheet( 10,10, "example")
+INHERIT(container);
+SIGNAL("activate", "Called when a child is activated");
+SIGNAL("deactivate", "Called when a child is deactivated");
+SIGNAL("new_column_width", "");
+SIGNAL("new_row_height", "");
+SIGNAL("select_row","");
+SIGNAL("select_column","");
+SIGNAL("select_range","");
+SIGNAL("clip_range","");
+SIGNAL("resize_range","");
+SIGNAL("move_range","");
+SIGNAL("traverse","");
+SIGNAL("set_cell","");
+SIGNAL("changed","");
+SIGNAL("new_column_width","");
+SIGNAL("new_row_height","");
+SIGNAL("set_scroll_adjustments","");
+
+
+static void push_gtk_sheet_range( GtkSheetRange range )
+{
+  push_text( "row0" ); push_int( range.row0 );
+  push_text( "rowi" ); push_int( range.rowi );
+  push_text( "col0" ); push_int( range.col0 );
+  push_text( "coli" ); push_int( range.coli );
+  f_aggregate_mapping( 8 );
+}
+
+static void push_gtk_sheet_border( GtkSheetCellBorder b )
+{
+  push_text( "mask" );        push_int( b.mask );
+  push_text( "width" );       push_int( b.width );
+  push_text( "line_style" );  push_int( b.line_style );
+  push_text( "cap_style" );   push_int( b.cap_style );
+  push_text( "join_style" );  push_int( b.join_style );
+  push_text( "color" );       
+  push_pgdkobject( &b.color, pgtk_GdkColor_program );
+  f_aggregate_mapping( 12 );
+}
+
+static void push_gtk_sheet_attr( GtkSheetAttr *a )
+{
+  push_text( "range" ); push_gtk_sheet_range( a->range );
+  push_text( "type" );  push_int( a->type );
+  push_text( "value" );
+  switch( a->type )
+  {
+  case GTK_SHEET_FOREGROUND:
+  case GTK_SHEET_BACKGROUND:
+    push_pgdkobject( &a->value.foreground, pgtk_GdkColor_program );
+    break;
+  case GTK_SHEET_BORDER_COLOR:
+    push_pgdkobject( &a->value.border.color, pgtk_GdkColor_program );
+    break;
+  case GTK_SHEET_FONT:
+    push_pgdkobject( a->value.font, pgtk_GdkFont_program );
+    break;
+  case GTK_SHEET_JUSTIFICATION:
+    push_int( a->value.justification );
+    break;
+  case GTK_SHEET_BORDER:
+    push_gtk_sheet_border( a->value.border );
+    break;
+  case GTK_SHEET_IS_EDITABLE:
+    push_int( a->value.is_editable );
+    break;
+  case GTK_SHEET_IS_VISIBLE:
+    push_int( a->value.is_visible );
+    break;
+  }
+  f_aggregate_mapping( 6 );
+}
+
+FUNCTION(get_attributes, "function(int,int:mapping)");
+{
+  int x, y;
+  GtkSheetCellAttr attr;
+  get_all_args( "get_attributes", args, "%d%d", &x, &y );
+  pop_n_elems( args );
+  if( gtk_sheet_get_attributes( GTK_SHEET(THIS->obj),x,y, &attr ) )
+  {
+    push_text("justification"); 
+    push_int( attr.justification );
+    push_text("font");
+    push_pgdkobject( &attr.font, pgtk_GdkFont_program );
+    push_text("foreground"); 
+    push_pgdkobject( &attr.foreground, pgtk_GdkColor_program );
+    push_text("background"); push_int( attr.justification );
+    push_pgdkobject( &attr.background, pgtk_GdkColor_program );
+    push_text("border");
+    push_gtk_sheet_border( attr.border );
+    push_text("is_editable");
+    push_int( attr.is_editable );
+    push_text("is_visible");
+    push_int( attr.is_visible );
+    f_aggregate_mapping( 14 );
+  }
+  else
+    push_int( 0 );
+}
+
+COMPLEX_FUNCTION(create, int, int, string);
+NAME_ARGS(rows,columns,title);
+entry COMPLEX_FUNCTION(get_entry);
+COMPLEX_FUNCTION(set_hadjustment, adjustment);
+COMPLEX_FUNCTION(set_vadjustment, adjustment);
+
+COMPLEX_FUNCTION(set_column_titles_height, int);
+NAME_ARGS(height);
+COMPLEX_FUNCTION(set_row_titles_width, int);
+NAME_ARGS(height);
+COMPLEX_FUNCTION(put,widget, int, int);
+NAME_ARGS(child,x,y);
+COMPLEX_FUNCTION(move_child,widget, int, int);
+NAME_ARGS(child,x,y);
+COMPLEX_FUNCTION(set_cell_text, int, int, string);
+int COMPLEX_FUNCTION(get_state);
+COMPLEX_FUNCTION(set_title, string);
+NAME_ARGS(title);
+/* COMPLEX_FUNCTION(set_border, int); */
+/* NAME_ARGS(border_style); */
+COMPLEX_FUNCTION(freeze);
+COMPLEX_FUNCTION(thaw);
+COMPLEX_FUNCTION(set_column_title, int, string);
+COMPLEX_FUNCTION(set_row_title, int, string);
+COMPLEX_FUNCTION(row_button_add_label, int, string);
+COMPLEX_FUNCTION(column_button_add_label, int, string);
+COMPLEX_FUNCTION(moveto,int,int,float,float);
+COMPLEX_FUNCTION(show_column_titles);
+COMPLEX_FUNCTION(show_row_titles);
+COMPLEX_FUNCTION(hide_column_titles);
+COMPLEX_FUNCTION(hide_row_titles);
+COMPLEX_FUNCTION(column_set_sensitivity,int,int);
+COMPLEX_FUNCTION(row_set_sensitivity,int,int);
+COMPLEX_FUNCTION(columns_set_sensitivity,int);
+COMPLEX_FUNCTION(rows_set_sensitivity,int);
+COMPLEX_FUNCTION(column_set_visibility,int,int);
+COMPLEX_FUNCTION(row_set_visibility,int,int);
+COMPLEX_FUNCTION(select_row,int);
+COMPLEX_FUNCTION(select_column,int);
+FUNCTION(clip_range, "function(int,int,int,int:object)");
+NAME_ARGS(x0,y0,x1,y1);
+{
+  GtkSheetRange r;
+  get_all_args( "clip_range", args, "%d%d%d%d", &r.col0,&r.row0,&r.coli,&r.rowi);
+  gtk_sheet_clip_range( GTK_SHEET( THIS->obj ), r );
+  RETURN_THIS();
+}
+COMPLEX_FUNCTION(unclip_range);
+adjustment COMPLEX_FUNCTION(get_vadjustment);
+adjustment COMPLEX_FUNCTION(get_hadjustment);
+FUNCTION(select_range, "function(void:mapping)");
+NAME_ARGS(x0,y0,x1,y1);
+{
+  GtkSheetRange r;
+  pop_n_elems(args);
+  gtk_sheet_select_range( GTK_SHEET( THIS->obj ), &r );
+  push_text( "x0" ); push_int( r.col0 );
+  push_text( "y0" ); push_int( r.row0 );
+  push_text( "x1" ); push_int( r.coli );
+  push_text( "y1" ); push_int( r.rowi );
+  f_aggregate_mapping( 4 );
+}
+FUNCTION(unselect_range, "function(void:mapping)");
+NAME_ARGS(x0,y0,x1,y1);
+{
+  GtkSheetRange r;
+  pop_n_elems(args);
+  gtk_sheet_unselect_range( GTK_SHEET( THIS->obj ), &r );
+  push_text( "x0" ); push_int( r.col0 );
+  push_text( "y0" ); push_int( r.row0 );
+  push_text( "x1" ); push_int( r.coli );
+  push_text( "y1" ); push_int( r.rowi );
+  f_aggregate_mapping( 4 );
+}
+int COMPLEX_FUNCTION(set_active_cell, int, int);
+FUNCTION(get_active_cell, "function(void:mapping)");
+{
+  int x, y;
+  pop_n_elems(args);
+  gtk_sheet_get_active_cell( GTK_SHEET(THIS->obj), &x, &y );
+  push_text( "row" ); push_int( x );
+  push_text( "col" ); push_int( y );
+  f_aggregate_mapping( 4 );
+}
+COMPLEX_FUNCTION(set_cell, int, int, int, string);
+NAME_ARGS(row, col, justification, text);
+string COMPLEX_FUNCTION(cell_get_text, int, int);
+COMPLEX_FUNCTION(cell_clear, int, int);
+FUNCTION(clear, "function(void:object)");
+{
+  pop_n_elems(args);
+  gtk_sheet_range_clear(GTK_SHEET(THIS->obj), NULL);
+  RETURN_THIS();
+}
+FUNCTION(range_clear, "function(int,int,int,int:object)");
+NAME_ARGS(x0,y0,x1,y1);
+{
+  GtkSheetRange r;
+  get_all_args( "clip_range", args, "%d%d%d%d", &r.col0,&r.row0,&r.coli,&r.rowi);
+  gtk_sheet_range_clear( GTK_SHEET( THIS->obj ), &r );
+  RETURN_THIS();
+}
+int COMPLEX_FUNCTION(cell_get_state, int, int);
+
+FUNCTION(get_pixel_info, "function(int,int:mapping)");
+{
+  int x, y, r, c;
+  get_all_args( "get_pixel_info", args, "%d%d", &x, &y );
+  
+  pop_n_elems(args);
+  gtk_sheet_get_pixel_info( GTK_SHEET(THIS->obj),x,y, &r, &c );
+  push_text( "row" ); push_int( r );
+  push_text( "col" ); push_int( c );
+  f_aggregate_mapping( 4 );
+}
+FUNCTION(range_set_foreground, "function(int,int,int,int,object:object)");
+NAME_ARGS(x0,y0,x1,y1,color);
+{
+  GtkSheetRange r;
+  struct object *c;
+  get_all_args( "range_set_foreground", args, "%d%d%d%d%o", 
+                &r.col0,&r.row0,&r.coli,&r.rowi,&c);
+  gtk_sheet_range_set_foreground( GTK_SHEET( THIS->obj ), 
+                                  r, get_gdkobject( c, Color ) );
+  RETURN_THIS();
+}
+FUNCTION(range_set_background, "function(int,int,int,int,object:object)");
+NAME_ARGS(x0,y0,x1,y1,color);
+{
+  GtkSheetRange r;
+  struct object *c;
+  get_all_args( "range_set_background", args, "%d%d%d%d%o", 
+                &r.col0,&r.row0,&r.coli,&r.rowi, &c);
+  gtk_sheet_range_set_background( GTK_SHEET( THIS->obj ), 
+                                  r, get_gdkobject( c, Color ) );
+  RETURN_THIS();
+}
+FUNCTION(range_set_font, "function(int,int,int,int,object:object)");
+NAME_ARGS(x0,y0,x1,y1,color);
+{
+  GtkSheetRange r;
+  struct object *c;
+  get_all_args( "range_set_background", args, "%d%d%d%d%o", 
+                &r.col0,&r.row0,&r.coli,&r.rowi, &c);
+  gtk_sheet_range_set_font( GTK_SHEET( THIS->obj ), 
+                            r, get_gdkobject( c, Font ) );
+  RETURN_THIS();
+}
+FUNCTION(range_set_border_color, "function(int,int,int,int,object:object)");
+NAME_ARGS(x0,y0,x1,y1,color);
+{
+  GtkSheetRange r;
+  struct object *c;
+  get_all_args( "range_set_border_color", args, "%d%d%d%d%o", 
+                &r.col0,&r.row0,&r.coli,&r.rowi, &c);
+  gtk_sheet_range_set_border_color( GTK_SHEET( THIS->obj ), 
+                                    r, get_gdkobject( c, Color ) );
+  RETURN_THIS();
+}
+FUNCTION(range_set_justification, "function(int,int,int,int,int:object)");
+NAME_ARGS(x0,y0,x1,y1,justification);
+{
+  GtkSheetRange r;
+  int f;
+  get_all_args( "range_set_justification", args, "%d%d%d%d%d", 
+                &r.col0,&r.row0,&r.coli,&r.rowi,&f);
+  gtk_sheet_range_set_justification( GTK_SHEET( THIS->obj ), r, f );
+  RETURN_THIS();
+}
+FUNCTION(range_set_editable, "function(int,int,int,int,int:object)");
+NAME_ARGS(x0,y0,x1,y1,editable);
+{
+  GtkSheetRange r;
+  int f;
+  get_all_args( "range_set_justification", args, "%d%d%d%d%d", 
+                &r.col0,&r.row0,&r.coli,&r.rowi,&f);
+  gtk_sheet_range_set_editable( GTK_SHEET( THIS->obj ), r, f );
+  RETURN_THIS();
+}
+FUNCTION(range_set_visible, "function(int,int,int,int,int:object)");
+NAME_ARGS(x0,y0,x1,y1,visible);
+{
+  GtkSheetRange r;
+  int f;
+  get_all_args( "range_set_justification", args, "%d%d%d%d%d", 
+                &r.col0,&r.row0,&r.coli,&r.rowi,&f);
+  gtk_sheet_range_set_visible( GTK_SHEET( THIS->obj ), r, f );
+  RETURN_THIS();
+}
+FUNCTION(range_set_border, "function(int,int,int,int,int:object)");
+NAME_ARGS(x0,y0,x1,y1,mask,width,style);
+{
+  GtkSheetRange r;
+  int f,q,w;
+  get_all_args( "range_set_border", args, "%d%d%d%d%d%d%d", 
+                &r.col0,&r.row0,&r.coli,&r.rowi,&f,&q,&w);
+  gtk_sheet_range_set_border( GTK_SHEET( THIS->obj ), r, f,q,w );
+  RETURN_THIS();
+}
+COMPLEX_FUNCTION(column_set_justification, int, int);
+NAME_ARGS(column,justification);
+// justification is one of CONST(GTK_JUSTIFY)
+
+
+COMPLEX_FUNCTION(set_column_width,int,int);
+COMPLEX_FUNCTION(set_row_height,int,int);
+COMPLEX_FUNCTION(add_column,int);
+COMPLEX_FUNCTION(add_row,int);
+COMPLEX_FUNCTION(insert_columns,int,int);
+COMPLEX_FUNCTION(insert_rows,int,int);
+COMPLEX_FUNCTION(delete_columns,int,int);
+COMPLEX_FUNCTION(delete_rows,int,int);
+
+CLASSMEMBER(flags, int);
+CLASSMEMBER(maxrow, int);
+CLASSMEMBER(maxcol, int);
+CLASSMEMBER(maxallocrow, int);
+CLASSMEMBER(maxalloccol, int);
+CLASSMEMBER(maxrange, int);
+CLASSMEMBER(hoffset, int);
+CLASSMEMBER(voffset, int);
+CLASSMEMBER(shadow_type, int);
+END_COND_WIDGET(sheet);
diff --git a/src/post_modules/GTK/source/gtksocket.pre b/src/post_modules/GTK/source/gtksocket.pre
new file mode 100644
index 0000000000000000000000000000000000000000..582a8c74a04372b9502a914ef866494968b9da01
--- /dev/null
+++ b/src/post_modules/GTK/source/gtksocket.pre
@@ -0,0 +1,50 @@
+PROGRAM(socket);
+// Together with W(Plug), GTK.Socket provides the ability to embed
+// widgets from one process into another process in a fashion that is
+// transparent to the user. One process creates a GTK.Socket widget
+// and, passes the XID of that widget's window to the other process,
+// which then creates a W(Plug) window with that XID. Any widgets
+// contained in the W(Plug) then will appear inside the first
+// applications window.
+// <p>
+// Note that if you pass the XID of the socket to another process
+// that will create a plug in the socket, you must make sure that the
+// socket widget is not destroyed until that plug is
+// created. Violating this rule will cause unpredictable
+// consequences, the most likely consequence being that the plug will
+// appear as a separate toplevel window.
+// <p>
+//  A socket can also be used to swallow arbitrary pre-existing
+//  top-level windows using steal(), though the integration when this
+//  is done will not be as close as between a W(Plug) and a
+//  GTK.Socket
+INHERIT(container);
+COMPLEX_FUNCTION(create);
+COMPLEX_FUNCTION(steal, int);
+NAME_ARGS(window_id);
+// Reparents a pre-existing toplevel window (not nessesarily a GTK
+// window) into a socket.
+FUNCTION(id, "function(void:int)");
+// Returns the window id, to be sent to the application providing the plug.
+// <br>You must realize this widget before calling this function.
+{
+  if( !GTK_WIDGET( THIS->obj )->window )
+    error("You must realize this widget before calling this function.\n");
+  pop_n_elems( args );
+  push_int(GDK_WINDOW_XWINDOW( GTK_WIDGET( THIS->obj )->window ));
+}
+
+FUNCTION(has_plug, "function(void:int)");
+// Returns true if this socket is occupied
+{
+  pop_n_elems( args );
+  if( GTK_SOCKET( THIS->obj )->plug_window 
+      || gtk_container_children( GTK_CONTAINER( THIS->obj )) )
+    push_int( 1 );
+  else
+    push_int( 0 );
+}
+
+CLASSMEMBER(same_app,int);
+// return 1 if the widow contained in this socket comes from this
+// process.
diff --git a/src/post_modules/GTK/source/gtkspinbutton.pre b/src/post_modules/GTK/source/gtkspinbutton.pre
new file mode 100644
index 0000000000000000000000000000000000000000..81f163e5c121479b8f9535fdda2f17c2d28b9dac
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkspinbutton.pre
@@ -0,0 +1,134 @@
+PROGRAM(spin_button);
+// The Spin Button widget is generally used to allow the user to
+// select a value from a range of numeric values. It consists of a
+// text entry box with up and down arrow buttons attached to the
+// side. Selecting one of the buttons causes the value to "spin" up
+// and down the range of possible values. The entry box may also be
+// edited directly to enter a specific value.
+
+// <p>
+
+// The Spin Button allows the value to have zero or a number of
+// decimal places and to be incremented/decremented in configurable
+// steps. The action of holding down one of the buttons optionally
+// results in an acceleration of change in the value according to how
+// long it is depressed.
+
+// <p>
+
+// The Spin Button uses an Adjustment object to hold information about
+// the range of values that the spin button can take.
+
+// <p>
+
+// The attributes of an Adjustment are used by the Spin Button in the
+// following way:
+// <ul><li>value: initial value for the Spin Button 
+//     <li>lower: lower range value 
+//     <li>upper: upper range value 
+//     <li>step_increment: value to increment/decrement when pressing mouse button 1 on a button 
+//     <li>page_increment: value to increment/decrement when pressing mouse button 2 on a button 
+//     <li>page_size: unused
+// </ul>
+// <p>
+// The argument order for the W(Adjustment) constructor is:<br>
+// value, lower, upper, step_increment, page_increment, page_size<br>
+// 
+// IMG: GTK.SpinButton( GTK.Adjustment(),0.1, 1 )->set_usize(60,20)
+// <p>
+INHERIT(entry);
+COMPLEX_FUNCTION(create, adjustment, float, int);
+NAME_ARGS(range,climb_rate,precision);
+//  The climb_rate argument take a value between 0.0 and 1.0 and
+//  indicates the amount of acceleration that the Spin Button has. The
+//  digits argument specifies the number of decimal places to which
+//  the value will be displayed.
+COMPLEX_FUNCTION(configure, adjustment, float, int);
+NAME_ARGS(range,climb_rate,precision);
+// Adjustment (with the lower/upper/increse values), climb_rate and digits
+COMPLEX_FUNCTION(set_adjustment, adjustment);
+NAME_ARGS(range);
+// Set a new adjustment.
+COMPLEX_FUNCTION(set_digits, int);
+NAME_ARGS(precision);
+// Set the number of digits to show to the user.
+float COMPLEX_FUNCTION(get_value_as_float);
+// The current value of a Spin Button can be retrieved as a float.
+int COMPLEX_FUNCTION(get_value_as_int);
+// The current value of a Spin Button can be retrieved as a int.
+
+COMPLEX_FUNCTION(set_value, float);
+NAME_ARGS(to);
+// Set the value.
+COMPLEX_FUNCTION(set_update_policy, int);
+NAME_ARGS(policy);
+// The possible values of policy are either GTK.UpdateAlways or
+// GTK.UpdateIfValid.
+// <p>
+// These policies affect the behavior of a Spin Button when parsing
+// inserted text and syncing its value with the values of the
+// Adjustment.
+// <p>
+// In the case of GTK.UpdateIfValid the Spin Button value only gets
+// changed if the text input is a numeric value that is within the
+// range specified by the Adjustment. Otherwise the text is reset 
+// to the current value. 
+// <p>
+// In case of GTK.UpdateAlways errors are ignored while converting text
+// into a numeric value.
+COMPLEX_FUNCTION(set_numeric, int);
+NAME_ARGS(numericp);
+// If true, it is a numeric value.  This prevents a user from typing
+// anything other than numeric values into the text box of a Spin
+// Button
+COMPLEX_FUNCTION(spin, int, float);
+NAME_ARGS(direction,increment);
+// If you want to alter the value of a Spin Value relative to its
+// current value, then this ffunction can be used.
+// <p>
+// The direction paramenter is one of CONST(GTK_SPIN)
+// <p>
+//  GTK.SpinStepForward and GTK.SpinStepBackward change the value
+//  of the Spin Button by the amount specified by increment, unless
+//  increment is equal to 0, in which case the value is changed by the
+//  value of step_increment in theAdjustment.
+// <p>
+// GTK.SpinPageForward and GTK.SpinPageBackward simply alter the
+// value of the Spin Button by increment.
+// <p>
+// GTK.SpinHome sets the value of the Spin Button to the bottom of the
+// Adjustments range.
+// <p>
+// GTK.SpinEnd sets the value of the Spin Button to the top of the
+// Adjustments range.
+// <p>
+// GTK.SpinUserDefined simply alters the value of the Spin Button by
+// the specified amount.
+COMPLEX_FUNCTION(set_wrap, int);
+NAME_ARGS(wrapp);
+// If true, the spin button will wrap from the lowest to the highest
+// value, and the highest to the lowest.
+COMPLEX_FUNCTION(set_shadow_type,int);
+NAME_ARGS(type);
+// Type is one of CONST(GTK_SHADOW)
+COMPLEX_FUNCTION(set_snap_to_ticks,int);
+NAME_ARGS(snapp);
+// Set the Spin Button to round the value to the nearest
+// step_increment, which is set within the Adjustment object used with
+// the Spin Button
+COMPLEX_FUNCTION(update);
+// Explicitly request that the Spin Button updates itself
+
+CLASSMEMBER( climb_rate, float);
+// The amount of acceleration that the Spin Button has. 0.0 is no
+// accelleration and 1.0 is highest accelleration.
+CLASSMEMBER( update_policy, int);
+// The update policy. GTK_UPDATE_ALWAYS or GTK_UPDATE_IF_VALID.
+CLASSMEMBER( digits, int);
+// The number of decimal places to which the value will be displayed.
+CLASSMEMBER( numeric, int);
+// If != 0 the user can not enter anything but numeric values.
+CLASSMEMBER( wrap, int);
+// If != 0 the Spin Button will wrap around between the upper and lower range values.
+CLASSMEMBER( snap_to_ticks, int);
+// If != 0 the Spin Button will round the value to the nearest step_increment.
diff --git a/src/post_modules/GTK/source/gtkstatusbar.pre b/src/post_modules/GTK/source/gtkstatusbar.pre
new file mode 100644
index 0000000000000000000000000000000000000000..42ef9cdd089782a8e144cd07d92ab0c946c7caae
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkstatusbar.pre
@@ -0,0 +1,34 @@
+PROGRAM(statusbar);
+// Statusbars are simple widgets used to display a text message. They
+// keep a stack of the messages pushed onto them, so that popping the
+// current message will re-display the previous text message.
+//  <p>
+// In order to allow different parts of an application to use the same
+// statusbar to display messages, the statusbar widget issues Context
+// Identifiers which are used to identify different 'users'. The
+// message on top of the stack is the one displayed, no matter what
+// context it is in. Messages are stacked in last-in-first-out order,
+// not context identifier order.
+//  <p>
+// IMG: lambda() {object sb = GTK.Statusbar();int id = sb->get_context_id("test");sb->push(id,"A message");sb->push(id,"Another message");return sb;}()
+// IMG: lambda() {object sb = GTK.Statusbar();int id = sb->get_context_id("test");sb->push(id,"A message");sb->push(id,"Another message");sb->pop(id);return sb;}()
+SIGNAL("text_pushed", "");
+SIGNAL("text_poped", "");
+INHERIT(hbox);
+COMPLEX_FUNCTION(create);
+// Create a new statusbar widget
+int COMPLEX_FUNCTION(get_context_id, string);
+NAME_ARGS(context);
+// Create a new context id (or get the id of an old one). The argument
+// is any string. The return value can be used for -&gt;push() -&gt;pop()
+// and -&gt;remove later on.
+int COMPLEX_FUNCTION(push,int,string);
+NAME_ARGS(context,data);
+// Push a message onto the statusbar. The return value is an id that
+// can be passed to remove later on.
+COMPLEX_FUNCTION(pop, int);
+NAME_ARGS(context);
+// Remove the topmost message.
+COMPLEX_FUNCTION(remove, int, int);
+NAME_ARGS(context,id);
+// Remove the specified message (the message id is the second argument).
diff --git a/src/post_modules/GTK/source/gtkstyle.pre b/src/post_modules/GTK/source/gtkstyle.pre
new file mode 100644
index 0000000000000000000000000000000000000000..41ac3c7e687c55392de7f0e3d74d79d4b7ef840e
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkstyle.pre
@@ -0,0 +1,24 @@
+PROGRAM(style);
+INHERIT(draw);
+
+style COMPLEX_FUNCTION(copy);
+//  Copy this style, and return the new style object
+style COMPLEX_FUNCTION(attach, GdkWindow);
+NAME_ARGS(to);
+//   Attach a style to a window; this process allocates the colors and
+//   creates the GC's for the style - it specializes it to a
+//   particular visual and colormap. The process may involve the
+//   creation of a new style if the style has already been attached to
+//   a window with a different style and colormap.
+COMPLEX_FUNCTION(detach);
+//  Undo a previous attach
+COMPLEX_FUNCTION(apply_default_background, GdkWindow, int, int, ?GdkRectangle, int, int, int, int);
+NAME_ARGS( window, set_bgp, state_type, area, x, y, width, height );
+// Set the background of the specified window (or the subarea
+// indicated by the rectangle) to the default background for the state
+// specified by state_type.
+
+// <p>
+
+// If set_bgp is true, the background of the widget will be set,
+// otherwise it will only be drawn into the window.
diff --git a/src/post_modules/GTK/source/gtktable.pre b/src/post_modules/GTK/source/gtktable.pre
new file mode 100644
index 0000000000000000000000000000000000000000..95440cb80599afc871b698b2c2163f8313a0d1e9
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktable.pre
@@ -0,0 +1,97 @@
+PROGRAM(table);
+// The Gtk.Table allow the programmer to arrange widgets in rows and
+// columns, making it easy to align many widgets next to each other,
+// horizontally and vertically.
+
+// <p>
+
+// IMG: GTK.Table(2,2,0)->attach_defaults( GTK.Label("0,0"), 0, 1, 0, 1)->attach_defaults( GTK.Label("0,1"), 0, 1, 1, 2)->attach_defaults( GTK.Label("1,0"), 1, 2, 0, 1)->attach_defaults( GTK.Label("1,1"), 1, 2, 1, 2)->set_col_spacings(10)->set_row_spacings(10)
+// IMG: GTK.Table(2,2,0)->attach_defaults( GTK.Label("0,0-1,0"), 0, 2, 0, 1)->attach_defaults( GTK.Label("0,1"), 0, 1, 1, 2)->attach_defaults( GTK.Label("1,1"), 1, 2, 1, 2)->set_col_spacings(10)->set_row_spacings(10)
+INHERIT(container);
+COMPLEX_FUNCTION(create, int, int, int);
+NAME_ARGS(width,height,homogeneousp);
+// Used to create a new table widget. An initial size must be given by
+// specifying how many rows and columns the table should have,
+// although this can be changed later with resize().
+// <p>
+// There can never be more than 65535 colums nor more than 65535 rows.
+// <p>
+// setting homogeneousp to 1 forces the all tablecells to be exactly
+// the same size.
+COMPLEX_FUNCTION(resize,int,int);
+NAME_ARGS(rows,columns);
+// If you need to change a table's size after it has been created,
+// this function allows you to do so.
+
+COMPLEX_FUNCTION(attach, widget, int, int, int, int, int, int, int, int);
+NAME_ARGS(subwidget,left,right,top,bottom,xoptions,yoptions);
+// Syntax: table-&gt;attach(widget, left, right, top, bottom, xoptions, yoptions, xpad, ypad);
+
+// The left and right attach arguments specify where to place the
+// widget, and how many boxes to use. If you want a button in the
+// lower right table entry of our 2x2 table, and want it to fill that
+// entry ONLY. left_attach would be = 1, right_attach = 2, top_attach
+// = 1, bottom_attach = 2.
+// <p>
+// Now, if you wanted a widget to take up the whole top row of our 2x2
+// table, you'd use left_attach = 0, right_attach = 2, top_attach = 0,
+// bottom_attach = 1.
+// </p>
+// The xoptions and yoptions are used to specify packing options and
+// may be OR'ed together to allow multiple options.
+// <p>
+// These options are: 
+// <ul>
+
+// <li> GTK.Fill - If the table box is larger than the widget, and
+// GTK_FILL is specified, the widget will expand to use all the room
+// available.
+
+// <li> GTK.Shrink - If the table widget was allocated less space then
+// was requested (usually by the user resizing the window), then the
+// widgets would normally just be pushed off the bottom of the window
+// and disappear. If GTK_SHRINK is specified, the widgets will shrink
+// with the table.
+
+// <li> GTK.Expand - This will cause the table cell to expand to use
+// up any remaining space in the window.  </ul>
+// <p>
+// Padding is just like in boxes, creating a clear area around the
+// widget specified in pixels
+COMPLEX_FUNCTION(attach_defaults, widget, int, int, int, int);
+NAME_ARGS(subwidget,left,right,top,bottom);
+// As there are many options associated with attach(), this
+// convenience function provides the programmer with a means to add
+// children to a table with identical padding and expansion options.
+// <p>
+// xoptions, yoptions, xpadding and ypadding are all set the their
+// default values. For the options that is GTK.Fill|GTK.Expand. For
+// the padding it is 0.
+COMPLEX_FUNCTION(set_col_spacing, int, int);
+NAME_ARGS(x,spacing);
+// alters the amount of space between a given table column and the
+// adjacent columns.
+COMPLEX_FUNCTION(set_row_spacing, int, int);
+NAME_ARGS(y,spacing);
+// alters the amount of space between a given table row and the
+// adjacent rows.
+COMPLEX_FUNCTION(set_col_spacings, int);
+NAME_ARGS(spacing);
+// Sets the space between every column in the table equal to spacing.
+COMPLEX_FUNCTION(set_row_spacings, int);
+NAME_ARGS(spacing);
+// Sets the space between every row in the table equal to spacing.
+COMPLEX_FUNCTION(set_homogeneous, int);
+NAME_ARGS(homogeneousp);
+// Set the homogeneous flag.
+
+CLASSMEMBER(nrows,int);
+// The number of rows. Between 1 and 65535.
+CLASSMEMBER(ncols,int);
+// The number of columns. Between 1 and 65535.
+CLASSMEMBER(column_spacing,int);
+// The spacing between all columns, in pixels.
+CLASSMEMBER(row_spacing,int);
+// The spacing between all rows, in pixels.
+CLASSMEMBER(homogeneous,int);
+// If 1, all cells have exactly the same size
diff --git a/src/post_modules/GTK/source/gtktearoffmenuitem.pre b/src/post_modules/GTK/source/gtktearoffmenuitem.pre
new file mode 100644
index 0000000000000000000000000000000000000000..454010a5cbe362b1608e83fad6817fcfa2c3e98a
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktearoffmenuitem.pre
@@ -0,0 +1,20 @@
+PROGRAM(tearoff_menu_item);
+// a GTK.TearoffMenuItem is a special W(MenuItem) which is used to
+// tear off and reattach its menu.
+// <p>
+// When its menu is shown normally, the GTK.TearoffMenuItem is drawn
+// as a dotted line indicating that the menu can be torn
+// off. Activating it causes its menu to be torn off and displayed in
+// its own window as a tearoff menu.
+// <p>
+// When its menu is shown as a tearoff menu, the GTK.TearoffMenuItem
+// is drawn as a dotted line which has a left pointing arrow graphic
+// indicating that the tearoff menu can be reattached. Activating it
+// will erase the tearoff menu window.
+// <p> IMG: GTK.TearoffMenuItem()->set_usize( 100,0 )
+INHERIT(menu_item);
+COMPLEX_FUNCTION(create);
+// Create a new tear of menu item
+CLASSMEMBER(torn_off, int);
+// Return 1 if the menu the menu item is connected to is currently
+// torn off.
diff --git a/src/post_modules/GTK/source/gtktext.pre b/src/post_modules/GTK/source/gtktext.pre
new file mode 100644
index 0000000000000000000000000000000000000000..c5daf850b7138d18021ef20357480b4205bf437e
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktext.pre
@@ -0,0 +1,128 @@
+/* -*- c -*- */
+PROGRAM(text);
+// The Text widget allows multiple lines of text to be displayed and
+// edited. It supports both multi-colored and multi-font text,
+// allowing them to be mixed in any way we wish. It also has a wide
+// set of key based text editing commands, which are compatible with
+// Emacs.
+// <p>
+// The text widget supports full cut-and-paste facilities, including
+// the use of double- and triple-click to select a word and a whole
+// line, respectively.
+// <p>
+// Bugs:<ul>
+//      <li> You cannot add text to the widget before it is realized.
+//     </ul>
+// IMG: GTK.Text(GTK.Adjustment(),GTK.Adjustment())
+// IMG: function_object(call_out(GTK.Text(GTK.Adjustment(),GTK.Adjustment())->set_text, 0, "Some text")[0])
+// IMG: function_object(call_out(GTK.Text(GTK.Adjustment(),GTK.Adjustment())->insert, 0, "Some text", 0, GDK.Color(255,255,0), GDK.Color(0,0,0))[0])
+
+INHERIT(editable);
+COMPLEX_FUNCTION(create, ?adjustment, ?adjustment);
+NAME_ARGS(xadjustment,yadjustment);
+//  Creates a new GTK.Text widget, initialized with the given
+//  Gtk.Adjustments. These pointers can be used to track the viewing
+//  position of the GTK.Text widget. Passing NULL to either or both of
+//  them will make the text widget create it's own. You can set these
+//  later with the function gtk_text_set_adjustment()
+COMPLEX_FUNCTION(set_editable, int);
+NAME_ARGS(editablep);
+// If true, the user can change the text in the widget.
+COMPLEX_FUNCTION(set_word_wrap, int);
+NAME_ARGS(wordwrapp);
+// If true, the widget will automatically wrap the contents.
+COMPLEX_FUNCTION(set_line_wrap, int);
+NAME_ARGS(linewrapp);
+// If true, the widget will automatically wrap the contents.
+COMPLEX_FUNCTION(set_adjustments, adjustment, adjustment);
+NAME_ARGS(xadjustment,yadjustment);
+// Change the adjustments (as supplied to the constructor) to other
+// adjustments.
+COMPLEX_FUNCTION(set_point, int);
+NAME_ARGS(point);
+// Sets the cursor at the given point. In this case a point
+// constitutes the number of characters from the extreme upper left
+// corner of the widget.
+int COMPLEX_FUNCTION(get_point);
+// Gets the current position of the cursor as the number of characters
+// from the upper left corner of the GtkText widget.
+int COMPLEX_FUNCTION(get_length);
+// Returns the length of the all the text contained within the widget
+SIMPLE_FUNCTION(freeze);
+// Freezes the widget which disallows redrawing of the widget until it
+// is thawed. This is useful if a large number of changes are going to
+// made to the text within the widget, reducing the amount of flicker
+// seen by the user.
+SIMPLE_FUNCTION(thaw);
+// unfreeze the widget.
+FUNCTION(insert, "function(string,void|object,void|object,void|object:object)");
+ARGS(string,GDK.Font,GDK.Color,GDK.Color);
+RETURNS(GTK.Text);
+NAME_ARGS(string,font,bg,fg);
+// syntax:<p>
+// object insert(string what); OR<br>
+// object insert(string what, GDK.Font font, GDK.Color fg, GDK.Color bg); OR<br>
+// object insert(string what, 0, GDK.Color fg, GDK.Color bg); OR<br>
+// object insert(string what, 0, GDK.Color fg); OR<br>
+// object insert(string what, 0, 0, GDK.Color bg);<br>
+// <p>
+//
+// Insert new text, optionally with colors. 
+{
+  struct svalue *a, *b, *c;
+  struct pike_string *s;
+  GdkFont *font = 0;
+  GdkColor *fg=0, *bg=0;
+  if(args == 4)
+  {
+    get_all_args("insert", args, "%S%*%*%*", &s,&a,&b,&c);
+
+    if(a->type == T_OBJECT)
+      font = get_gdkobject( a->u.object,Font );
+    
+    if(b->type == T_OBJECT)
+      fg = get_gdkobject( b->u.object,Color );
+
+    if(c->type == T_OBJECT)
+      bg = get_gdkobject( c->u.object,Color );
+  } else
+    get_all_args("insert", args, "%S", &s);
+    
+  gtk_text_insert( GTK_TEXT( THIS->obj ), font, fg, bg, s->str, s->len );
+
+  RETURN_THIS();
+}
+
+COMPLEX_FUNCTION(backward_delete, int);
+NAME_ARGS(nchars);
+// Delete n characters backwards from the cursor position
+COMPLEX_FUNCTION(forward_delete, int);
+NAME_ARGS(nchars);
+// Delete n characters forward from the cursor position
+
+FUNCTION(set_text, "function(string:object)")
+NAME_ARGS(to);
+// Set the text to the specified string.
+{
+  gtk_text_freeze( GTK_TEXT( THIS->obj ) );
+  gtk_text_set_point( GTK_TEXT( THIS->obj ), 0 );
+  gtk_text_forward_delete( GTK_TEXT( THIS->obj ), 
+			   gtk_text_get_length( GTK_TEXT( THIS->obj ) ) );
+  pgtk_text_insert( 1 );
+  gtk_text_thaw( GTK_TEXT( THIS->obj ) );
+  RETURN_THIS();
+}
+
+FUNCTION(get_text, "function(void:string)")
+// Get the current contents of the text object.
+{
+  struct pike_string *res;
+  unsigned int i;
+  pop_n_elems(args);
+  res = begin_shared_string( gtk_text_get_length( GTK_TEXT( THIS->obj ) ) );
+  for(i=0; i<(unsigned int)res->len; i++)
+    res->str[i] = GTK_TEXT_INDEX( GTK_TEXT( THIS->obj ), i );
+  push_string( end_shared_string( res ) );
+}
+
+/* FIXME: Wide string support! */
diff --git a/src/post_modules/GTK/source/gtktipsquery.pre b/src/post_modules/GTK/source/gtktipsquery.pre
new file mode 100644
index 0000000000000000000000000000000000000000..e91b20a0df2c8644ba14eaa2b654ee275c27b4b8
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktipsquery.pre
@@ -0,0 +1,19 @@
+PROGRAM(tips_query); 
+SIGNAL("start_query","");
+SIGNAL("stop_query","");
+SIGNAL("widget_entered","");
+SIGNAL("widget_selected","");
+INHERIT(label);
+COMPLEX_FUNCTION(create);
+COMPLEX_FUNCTION(start_query);
+COMPLEX_FUNCTION(stop_query);
+COMPLEX_FUNCTION(set_caller,widget);
+NAME_ARGS(caller_widget);
+COMPLEX_FUNCTION(set_labels,string,string);
+NAME_ARGS(label_inactive,label_no_tip);
+
+CLASSMEMBER(in_query,int);
+CLASSMEMBER(label_inactive,string);
+CLASSMEMBER(label_no_tip,string);
+SUBWIDGET(caller,widget);
+SUBWIDGET(last_crossed,widget);
diff --git a/src/post_modules/GTK/source/gtktogglebutton.pre b/src/post_modules/GTK/source/gtktogglebutton.pre
new file mode 100644
index 0000000000000000000000000000000000000000..8fd0fe2a25ad425dd55f2754fee7b43e84c70be7
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktogglebutton.pre
@@ -0,0 +1,40 @@
+PROGRAM(toggle_button);
+// Toggle buttons are derived from normal buttons and are very
+// similar, except they will always be in one of two states,
+// alternated by a click. They may be depressed, and when you click
+// again, they will pop back up. Click again, and they will pop back
+// down.
+// <p>
+// IMG: GTK.ToggleButton("Toggle button")
+// IMG: GTK.ToggleButton("Toggle button")->set_active( 1 )
+SIGNAL("toggled", "");
+INHERIT(button);
+FUNCTION(create, "function(string|void:void)");
+NAME_ARGS(label);
+// If you supply a string, a label will be created and inserted in the button.
+// Otherwise, use -&gt;add(widget) to create the contents of the button.
+{
+  if(THIS->obj) error("GTK.Toggle_button->create() can only be called once.\n");
+  if(args)
+  {
+    char *s;
+    get_all_args("GTK.Toggle_button", args, "%s", &s);
+    THIS->obj = GTK_OBJECT( gtk_toggle_button_new_with_label( s ) );
+  } else {
+    THIS->obj = GTK_OBJECT( gtk_toggle_button_new( ) );
+  }
+  pgtk__init_this_object();
+}
+COMPLEX_FUNCTION(set_mode, int);
+NAME_ARGS(mode);
+// If true, draw indicator
+COMPLEX_FUNCTION(set_active, int);
+NAME_ARGS(activep);
+// If activep is true, the toggle button will be activated.
+/* int COMPLEX_FUNCTION(get_active); */
+CLASSMEMBER(active, int);
+// returns 1 if the button is pressed, 0 otherwise.
+SIMPLE_FUNCTION(toggled);
+// emulate a 'toggle' of the button. This will emit a 'toggled' signal.
+
+/* CLASSMEMBER(draw_indicator,int); */
diff --git a/src/post_modules/GTK/source/gtktoolbar.pre b/src/post_modules/GTK/source/gtktoolbar.pre
new file mode 100644
index 0000000000000000000000000000000000000000..14e7c8a4fe7d214a9bd9b11d416eb3c0b4e841fc
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktoolbar.pre
@@ -0,0 +1,69 @@
+PROGRAM(toolbar);
+// Toolbars are usually used to group some number of widgets in order
+// to simplify customization of their look and layout. Typically a
+// toolbar consists of buttons with icons, labels and tooltips, but
+// any other widget can also be put inside a toolbar. Finally, items
+// can be arranged horizontally or vertically and buttons can be
+// displayed with icons, labels, or both.
+
+// <p>
+// Examples:
+// IMG: lambda(){object t=GTK.Toolbar( GTK.ORIENTATION_HORIZONTAL, GTK.TOOLBAR_TEXT );t->append_item( "Button 1", "Tooltip 1", "", GTK.Frame(), lambda(){},0);t->append_space();t->append_item( "Button 2", "Tooltip 2", "", GTK.Frame(), lambda(){},0);t->append_item( "Button 3", "Tooltip 3", "", GTK.Frame(), lambda(){},0);t->append_space();t->append_item( "Button 4", "Tooltip 4", "", GTK.Frame(), lambda(){},0);t->append_item( "Button 5", "Tooltip 5", "", GTK.Frame(), lambda(){},0);return t;}()
+// IMG: lambda(){object t=GTK.Toolbar( GTK.ORIENTATION_VERTICAL, GTK.TOOLBAR_TEXT );t->append_item( "Button 1", "Tooltip 1", "", GTK.Frame(), lambda(){},0);t->append_space();t->append_item( "Button 2", "Tooltip 2", "", GTK.Frame(), lambda(){},0);t->append_item( "Button 3", "Tooltip 3", "", GTK.Frame(), lambda(){},0);t->append_space();t->append_item( "Button 4", "Tooltip 4", "", GTK.Frame(), lambda(){},0);t->append_item( "Button 5", "Tooltip 5", "", GTK.Frame(), lambda(){},0);return t;}()
+// IMG: lambda(){object i=GDK.Image()->set(Image.image(20,20)->test());object t=GTK.Toolbar( GTK.ORIENTATION_HORIZONTAL, GTK.TOOLBAR_BOTH );t->append_item( "Button 1", "Tooltip 1", "", GTK.Image(i), lambda(){},0);t->append_space();t->append_item( "Button 2", "Tooltip 2", "", GTK.Image(i), lambda(){},0);t->append_item( "Button 3", "Tooltip 3", "", GTK.Image(i), lambda(){},0);t->append_space();t->append_item( "Button 4", "Tooltip 4", "", GTK.Image(i), lambda(){},0);t->append_item( "Button 5", "Tooltip 5", "", GTK.Image(i), lambda(){},0);return t;}()
+SIGNAL("orientation_changed", "");
+SIGNAL("style_changed", "");
+INHERIT(container);
+COMPLEX_FUNCTION(create, int, int);
+NAME_ARGS(orientation,style);
+// Orientation is one of
+// CONST(GTK_ORIENTATION). Style is one of CONST(GTK_TOOLBAR)
+
+COMPLEX_FUNCTION(append_item,  string, string, string, widget,  callback);
+NAME_ARGS(label,tooltip,private,icon,clicked,cbargument);
+// Arguments are: Label, Tooltip, Private data, Icon, clicked_callback_function, clicked_callback_argument.
+// <p>Adds a new button to the start of the toolbar. 
+COMPLEX_FUNCTION(prepend_item, string, string, string, widget,  callback);
+NAME_ARGS(label,tooltip,private,icon,clicked,cbargument);
+// Arguments as for append_item
+// <p>Adds a new button to the end of the toolbar. 
+COMPLEX_FUNCTION(insert_item,  string, string, string, widget,  callback, int);
+NAME_ARGS(label,tooltip,private,icon,clicked,cbargument,pos);
+// Arguments as for append_item, but an extra position argument at the end.
+// <p>Adds a new button after the item at the specified position.
+SIMPLE_FUNCTION(append_space);
+// Adds a small space.
+SIMPLE_FUNCTION(prepend_space);
+// Adds a small space.
+SIMPLE_INT_FUNCTION(insert_space);
+NAME_ARGS(pixels);
+// Inserts a small space at the specified postion.
+
+COMPLEX_FUNCTION(append_widget, widget, string, string);
+NAME_ARGS(widget,tootip,private);
+// Append a custom widgets. Arguments are widget, tooltip, private
+COMPLEX_FUNCTION(prepend_widget, widget, string, string);
+NAME_ARGS(widget,tootip,private);
+// Prepend a custom widgets. Arguments are widget, tooltip, private
+COMPLEX_FUNCTION(insert_widget, widget, string, string, int);
+NAME_ARGS(widget,tootip,private,pos);
+// Insert a custom widgets.
+
+COMPLEX_FUNCTION(set_orientation, int);
+NAME_ARGS(orientation);
+// Set the orientation, one of CONST(GTK_ORIENTATION)
+COMPLEX_FUNCTION(set_style, int);
+NAME_ARGS(style);
+// Set the style, one of CONST(GTK_TOOLBAR)
+COMPLEX_FUNCTION(set_space_size, int);
+NAME_ARGS(pixels);
+// Set the width (or height) of the space created by append_space.
+COMPLEX_FUNCTION(set_space_style, int);
+NAME_ARGS(style);
+COMPLEX_FUNCTION(set_tooltips, int);
+NAME_ARGS(tootipp);
+// If true, show the tooltips.
+
+COMPLEX_FUNCTION(set_button_relief, int);
+NAME_ARGS(relief);
+int COMPLEX_FUNCTION(get_button_relief);
diff --git a/src/post_modules/GTK/source/gtktooltips.pre b/src/post_modules/GTK/source/gtktooltips.pre
new file mode 100644
index 0000000000000000000000000000000000000000..ea5f21ee4514d8696f534f8c8ceafec6aee7962f
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktooltips.pre
@@ -0,0 +1,60 @@
+PROGRAM(tooltips);
+// Tooltips are the messages that appear next to a widget when the
+// mouse pointer is held over it for a short amount of time. They are
+// especially helpful for adding more verbose descriptions of things
+// such as buttons in a toolbar.
+
+// <p>
+
+// An individual tooltip belongs to a group of tooltips. A group is
+// created with a call to GTK.Tooltips(). Every tooltip in the
+// group can then be turned off with a call to disable()
+// and enabled with enable().
+
+// <p>
+
+// The length of time the user must keep the mouse over a widget
+// before the tip is shown, can be altered with set_delay(). This is
+// set on a 'per group of tooltips' basis.
+
+// <p>
+
+// To assign a tip to a particular W(Widget), set_tip() is used.
+
+// <p>
+
+// The default appearance of all tooltips in a program is determined
+// by the current gtk theme that the user has selected. To change the
+// tooltip appearance manually, use set_colors(). Again, this is per
+// group of tooltips.
+INHERIT(data);
+COMPLEX_FUNCTION(create);
+// Creates an empty group of tooltips. This function initialises a
+// GTK.Tooltips structure. Without at least one such structure, you
+// can not add tips to your application.
+SIMPLE_FUNCTION(enable);
+// Enable this tooltip collection
+SIMPLE_FUNCTION(disable);
+// Disable this tooltip collection
+COMPLEX_FUNCTION(set_delay, int);
+NAME_ARGS(delay);
+// Set the delat (in seconds)
+COMPLEX_FUNCTION(set_tip, widget, string, null);
+NAME_ARGS(in,to);
+// Adds a tooltip containing the message tip_text to the specified
+// W(Widget).
+FUNCTION(set_colors, "function(object,object:object)");
+ARGS(GDK.Color,GDK.Color);
+NAME_ARGS(foreground,background);
+RETURNS(GTK.Tooltips);
+// Changes the foreground and background colors.
+{
+  struct object *fg, *bg;
+  get_all_args("set_colors", args, "%o%o", &fg, &bg);
+  gtk_tooltips_set_colors( GTK_TOOLTIPS( THIS->obj ), 
+			   get_gdkobject( fg,Color ),
+			   get_gdkobject( bg,Color ) );
+  RETURN_THIS();
+}
+SIMPLE_FUNCTION(force_window);
+// Realize the tooltip window (as returned from get_gdkwindow())
diff --git a/src/post_modules/GTK/source/gtktree.pre b/src/post_modules/GTK/source/gtktree.pre
new file mode 100644
index 0000000000000000000000000000000000000000..bb2938d82f6ed0c421bf71577e7dbe0638cbe6f9
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktree.pre
@@ -0,0 +1,49 @@
+PROGRAM(tree);
+// A 'tree' with subnodes etc.  Do not have a tree with more than 100
+// or so entries. It will be very slow.<br>
+// Whenever possible, use W(Ctree) instead, it's way faster.
+// <p>
+// IMG: lambda() { object t = GTK.Tree();  object i, t2;  t->add(i = GTK.Tree_item("Sub node 1"));  i->set_subtree( GTK.Tree() );  t->add(i = GTK.Tree_item("Sub node 2"));  i->set_subtree( t2=GTK.Tree() );  call_out(i->expand, 0);  t2->add( GTK.Tree_item("Sub sub 1") );  t2->add( GTK.Tree_item("Sub sub 2") );  t->add(i = GTK.Tree_item("Sub node 3"));  i->set_subtree( GTK.Tree() );  return t;}()
+// IMG: lambda() { object t = GTK.Tree();  object i, t2;  t->add(i = GTK.Tree_item("Sub node 1"));  i->set_subtree( GTK.Tree() );  t->add(i = GTK.Tree_item("Sub node 2"));  i->set_subtree( t2=GTK.Tree() );  call_out(i->expand, 0);  t2->add( GTK.Tree_item("Sub sub 1") );  t2->add( GTK.Tree_item("Sub sub 2") );  t->add(i = GTK.Tree_item("Sub node 3"));  i->set_subtree( GTK.Tree() );  return t;}()->set_view_lines(0)
+SIGNAL("selection_changed", "");
+SIGNAL("select_child", "");
+SIGNAL("unselect_child", "");
+INHERIT(container);
+COMPLEX_FUNCTION(create);
+// Used to create a new tree widget.
+COMPLEX_FUNCTION(append, tree_item);
+NAME_ARGS(child);
+// Add a new tree item at insertion point
+COMPLEX_FUNCTION(prepend, tree_item);
+NAME_ARGS(child);
+// Add a new tree item from end (same as 'add')
+COMPLEX_FUNCTION(insert, tree_item, int);
+NAME_ARGS(child,pos);
+// Insert a new tree item at the specified position
+COMPLEX_FUNCTION(clear_items, int,int);
+NAME_ARGS(start,end);
+// Remove the items from position start to position end from a Tree.
+COMPLEX_FUNCTION(select_item, int);
+NAME_ARGS(pos);
+// Select a specified (by index) item
+COMPLEX_FUNCTION(unselect_item, int);
+NAME_ARGS(pos);
+// Unselect a specified (by index) item
+COMPLEX_FUNCTION(select_child, tree_item);
+NAME_ARGS(child);
+// Select a specified (by object) item
+COMPLEX_FUNCTION(unselect_child, tree_item);
+NAME_ARGS(child);
+// Unselect a specified (by object) item
+int COMPLEX_FUNCTION(child_position, tree_item);
+NAME_ARGS(child);
+// Unselect a specified (by object) item
+COMPLEX_FUNCTION(set_selection_mode, int);
+NAME_ARGS(selection_mode);
+// One of CONST(GTK_SELECTION)
+COMPLEX_FUNCTION(set_view_mode, int);
+NAME_ARGS(view_mode);
+// One of CONST(GTK_TREE)
+COMPLEX_FUNCTION(set_view_lines, int);
+NAME_ARGS(viewp);
+// if true, draw lines between the nodes
diff --git a/src/post_modules/GTK/source/gtktreeitem.pre b/src/post_modules/GTK/source/gtktreeitem.pre
new file mode 100644
index 0000000000000000000000000000000000000000..0b495d6bd9470316543b2db14e436d8a60b84ef2
--- /dev/null
+++ b/src/post_modules/GTK/source/gtktreeitem.pre
@@ -0,0 +1,43 @@
+PROGRAM(tree_item);
+// A item to be places in a W(Tree).
+// <br>The item can have a subtree attached to it.
+// <br>A subtree is a normal tree.
+SIGNAL("expand", "");
+SIGNAL("collapse", "");
+INHERIT(item);
+FUNCTION(create, "function(string|void:void)");
+NAME_ARGS(label);
+// If you specify a string it is used as a label, otherwise pack a widget
+// in the tree item with -&gt;add(widget).
+{
+  if(THIS->obj) error("GTK.Tree_item->create() can only be called once.\n");
+  if(args)
+  {
+    char *s;
+    get_all_args("GTK.Tree_item", args, "%s", &s);
+    THIS->obj = GTK_OBJECT( gtk_tree_item_new_with_label( s ) );
+  } else {
+    THIS->obj = GTK_OBJECT( gtk_tree_item_new( ) );
+  }
+  pgtk__init_this_object();
+}
+COMPLEX_FUNCTION(set_subtree, tree);
+NAME_ARGS(tree);
+// Sets the subtree. 
+SIMPLE_FUNCTION(remove_subtree);
+// Removes the subtree. 
+SIMPLE_FUNCTION(select);
+// Select this item. The item must be realized (the tree and all it's
+// parents shown) for this to work.<br>
+// This generates a 'select' event.
+SIMPLE_FUNCTION(deselect);
+// Deselect this item.<br>
+// This generates a 'deselect' event.
+SIMPLE_FUNCTION(expand);
+// Expand this subtree. The item must be realized (the tree and all it's
+// parents shown) for this to work.<br>
+// This generates a 'expand' event.
+SIMPLE_FUNCTION(collapse);
+// Collapse this subtree. The item must be realized (the tree and all it's
+// parents shown) for this to work.<br>
+// This generates a 'collapse' event.
diff --git a/src/post_modules/GTK/source/gtkvbox.pre b/src/post_modules/GTK/source/gtkvbox.pre
new file mode 100644
index 0000000000000000000000000000000000000000..eeff01f9f9a2979a7134a6c439e56a401e1a1f96
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkvbox.pre
@@ -0,0 +1,17 @@
+PROGRAM(vbox);
+// Most packing is done by creating boxes. These are invisible widget
+// containers that we can pack our widgets into which come in two
+// forms, a horizontal box, and a vertical box. This is the vertical
+// one.  When packing widgets into a vertical box, the objects are
+// inserted horizontally from top to bottom or bottom to top depending
+// on the call used.
+//
+// IMG: GTK.Vbox(0,0)->add(GTK.Button("Hello"))->add(GTK.Button("World"))->pack_end_defaults(GTK.Button("From right"))->pack_start_defaults(GTK.Button("From left"))
+// IMG: GTK.Vbox(1,0)->add(GTK.Button("Hello"))->add(GTK.Button("World"))->pack_end_defaults(GTK.Button("From right"))->pack_start_defaults(GTK.Button("From left"))
+// IMG: GTK.Vbox(1,40)->add(GTK.Button("Hello"))->add(GTK.Button("World"))->pack_end_defaults(GTK.Button("From right"))->pack_start_defaults(GTK.Button("From left"))
+INHERIT(box);
+COMPLEX_FUNCTION(create, int, int);
+NAME_ARGS(uniformp,padding);
+// Create a new horizontal box widget.
+// If all_same_size is true, all widgets will have exactly the same size.
+// padding is added to the top and bottom of the children.
diff --git a/src/post_modules/GTK/source/gtkvbuttonbox.pre b/src/post_modules/GTK/source/gtkvbuttonbox.pre
new file mode 100644
index 0000000000000000000000000000000000000000..b809ed88a84c68ef4a0f644ffa7681a2cd911601
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkvbuttonbox.pre
@@ -0,0 +1,14 @@
+PROGRAM(vbutton_box);
+// A Vbutton_box is very similar to a Vbox.
+// The major diffference is that the button box
+// is made to pack buttons in, and has a few convenience function for 
+// normal button layouts.
+// 
+// IMG: GTK.VbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_usize(100,300)
+// IMG: GTK.VbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_layout(GTK.BUTTONBOX_SPREAD)->set_usize(100,300)
+// IMG: GTK.VbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_layout(GTK.BUTTONBOX_EDGE)->set_usize(100,300)
+// IMG: GTK.VbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_layout(GTK.BUTTONBOX_START)->set_usize(100,300)
+// IMG: GTK.VbuttonBox()->add(GTK.Button("Hello"))->add(GTK.Button("World"))->set_layout(GTK.BUTTONBOX_END)->set_usize(100,300)
+INHERIT(button_box);
+COMPLEX_FUNCTION(create);
+// Create a new vertical button box
diff --git a/src/post_modules/GTK/source/gtkviewport.pre b/src/post_modules/GTK/source/gtkviewport.pre
new file mode 100644
index 0000000000000000000000000000000000000000..533054346bdfef661bf542dc5c5f00fe188ba347
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkviewport.pre
@@ -0,0 +1,28 @@
+PROGRAM(viewport);
+// This is a container that can be scrolled around, but it has no scrollbars.
+// You can connect scrollbars to it using the adjustment objects.
+// IMG: GTK.Viewport(GTK.Adjustment(),GTK.Adjustment())->set_usize(100,100)
+// IMG: GTK.Viewport(GTK.Adjustment(),GTK.Adjustment())->set_usize(100,100)->set_shadow_type(GTK.SHADOW_ETCHED_IN)
+// IMG: GTK.Viewport(GTK.Adjustment(),GTK.Adjustment())->set_usize(100,100)->add(GTK.Label("A label with a very long text on it, it will not fit"))->set_shadow_type(GTK.SHADOW_ETCHED_IN)
+// IMG: lambda(){ object a1;object v = GTK.Viewport(a1=GTK.Adjustment(),GTK.Adjustment())->set_usize(100,100)->add(GTK.Label("A label with a very long text on it, it will not fit"))->set_shadow_type(GTK.SHADOW_ETCHED_IN);call_out(a1->set_value,0,100.0);return v;}()
+INHERIT(bin);
+COMPLEX_FUNCTION(create, ?adjustment, ?adjustment);
+NAME_ARGS(xscroll,yscroll);
+// Create a new viewport.  The adjustments are used to select what
+// part of the viewport to view to the user. They are normally
+// connected to a scrollbar or something similar.
+adjustment COMPLEX_FUNCTION(get_hadjustment);
+// Return the current horizontal adjustment object
+adjustment COMPLEX_FUNCTION(get_vadjustment);
+// Return the current vertical adjustment object
+
+COMPLEX_FUNCTION(set_hadjustment, adjustment);
+NAME_ARGS(xscroll);
+// Set a new horizontal adjustment object.
+COMPLEX_FUNCTION(set_vadjustment, adjustment);
+NAME_ARGS(yscroll);
+// Set a new vertical adjustment object.
+COMPLEX_FUNCTION(set_shadow_type, int);
+NAME_ARGS(type);
+// Set the shadow style. One of CONST(GTK_SHADOW)
+
diff --git a/src/post_modules/GTK/source/gtkvpaned.pre b/src/post_modules/GTK/source/gtkvpaned.pre
new file mode 100644
index 0000000000000000000000000000000000000000..79916a39e1bca183c5a042af2d61bdfb495baeb9
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkvpaned.pre
@@ -0,0 +1,10 @@
+PROGRAM(vpaned);
+// The paned window widgets are useful when you want to divide an area
+// into two parts, with the relative size of the two parts controlled
+// by the user. A groove is drawn between the two portions with a
+// handle that the user can drag to change the ratio. This widgets
+// makes a vertical division
+//
+// IMG: GTK.Vpaned()->add1(GTK.Label("Top Side Of Pane"))->add2(GTK.Label("Bottom"))->set_usize(100,100)
+INHERIT(paned);
+COMPLEX_FUNCTION(create);
diff --git a/src/post_modules/GTK/source/gtkvruler.pre b/src/post_modules/GTK/source/gtkvruler.pre
new file mode 100644
index 0000000000000000000000000000000000000000..49b2363813b8553c41eb9a3918b19dfea527e740
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkvruler.pre
@@ -0,0 +1,13 @@
+PROGRAM(vruler);
+// Ruler widgets are used to indicate the location of the mouse
+// pointer in a given window. A window can have a vertical ruler
+// spanning across the width and a horizontal ruler spanning down the
+// height. A small triangular indicator on the ruler shows the exact
+// location of the pointer relative to the ruler.
+//
+// IMG: GTK.Vruler()->set_metric(GTK.PIXELS)->set_range(0.0,100.0,50.0,100.0)->draw_ticks()->draw_pos()->set_usize(30,50)
+// IMG: GTK.Vruler()->set_metric(GTK.CENTIMETERS)->set_range(0.0,100.0,50.0,100.0)->draw_ticks()->draw_pos()->set_usize(30,50)
+// IMG: GTK.Vruler()->set_usize(30,50)
+INHERIT(ruler);
+COMPLEX_FUNCTION(create);
+// Used to create a new vruler widget.
diff --git a/src/post_modules/GTK/source/gtkvscale.pre b/src/post_modules/GTK/source/gtkvscale.pre
new file mode 100644
index 0000000000000000000000000000000000000000..cdeb7ca93894495c5e54387a4f7a7d1db55fa76b
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkvscale.pre
@@ -0,0 +1,21 @@
+PROGRAM(vscale);
+// The GTK.VScale widget is used to allow the user to select a value
+// using a vertical slider. A GtkAdjustment is used to set the initial
+// value, the lower and upper bounds, and the step and page
+// increments.
+// <p>
+// The position to show the current value, and the number of decimal
+// places shown can be set using the parent W(Scale) class's
+// functions.
+// <p>
+// IMG: GTK.Vscale(GTK.Adjustment())->set_usize(30,100)
+INHERIT(scale);
+COMPLEX_FUNCTION(create, ?adjustment);
+NAME_ARGS(settings);
+// Used to create a new vscale widget.
+// The adjustment argument can either be an existing W(Adjustment), or
+// 0, in which case one will be created for you. Specifying 0 might
+// actually be useful in this case, if you wish to pass the newly
+// automatically created adjustment to the constructor function of
+// some other widget which will configure it for you, such as a text
+// widget.
diff --git a/src/post_modules/GTK/source/gtkvscrollbar.pre b/src/post_modules/GTK/source/gtkvscrollbar.pre
new file mode 100644
index 0000000000000000000000000000000000000000..b01598adf3e3d1f96db57f20a7ab345ea88c3e55
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkvscrollbar.pre
@@ -0,0 +1,15 @@
+PROGRAM(vscrollbar);
+// General documentation: See W(Scrollbar)
+// IMG: GTK.Vscrollbar(GTK.Adjustment())->set_usize(15,60)
+//
+INHERIT(scrollbar);
+COMPLEX_FUNCTION(create, ?adjustment);
+NAME_ARGS(pos);
+// Used to create a new vscrollbar widget.
+// The adjustment argument can either be an existing W(Adjustment), or
+// 0, in which case one will be created for you. Specifying 0 might
+// actually be useful in this case, if you wish to pass the newly
+// automatically created adjustment to the constructor function of
+// some other widget which will configure it for you, such as a text
+// widget.
+
diff --git a/src/post_modules/GTK/source/gtkvseparator.pre b/src/post_modules/GTK/source/gtkvseparator.pre
new file mode 100644
index 0000000000000000000000000000000000000000..a9660ed0e3d46cb2a84c284b90f5dc2c76623eb8
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkvseparator.pre
@@ -0,0 +1,6 @@
+PROGRAM(vseparator);
+// Simply creates a vertical separator. No bells or whistles.
+// IMG: GTK.Vseparator()->set_usize(3,50)
+INHERIT(separator);
+COMPLEX_FUNCTION(create);
+// Used to create a new vseparator widget.
diff --git a/src/post_modules/GTK/source/gtkwidget.pre b/src/post_modules/GTK/source/gtkwidget.pre
new file mode 100644
index 0000000000000000000000000000000000000000..bc5a273f35961d744955cc74724f75512d460a0c
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkwidget.pre
@@ -0,0 +1,789 @@
+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.
+// <p>
+// One of the most importat functions in this class is 'show',
+// it lets GTK know that we are done setting the attributes of the
+// widget, and it is ready to be displayed. You may also use hide to
+// make it disappear again. The order in which you show the widgets is
+// not important, but I suggest showing the toplevel window last so
+// the whole window pops up at once rather than seeing the individual
+// widgets come up on the screen as they're formed. The children of a
+// widget (a window is a widget too) will not be displayed until the
+// window itself is shown using the show() function.
+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", "Called when the widget is realized. Some methods cannot be used until the widget has been realized, if you get assertion errors related to 'w->window' or similar, this is probably the cause.");
+SIGNAL("unrealize", "Called when the widget is unrealized.");
+SIGNAL("draw", "Called when the widget should draw itself.");
+SIGNAL("draw_focus", "Called when the widget should draw itself, and a focus indicator around itself (or otherwise indicate that is has the keyboard focus)");
+SIGNAL("draw_default", "Called when the widget should draw itself, and indicate that it's the default widget");
+SIGNAL("add_accelerator", "Called when an accelarator (keyboard shortcut) is added to the widget");
+SIGNAL("remove_accelerator", "Called when an accelerator (keyboard shortcut) is removed from the widget");
+SIGNAL("size_request", "Called when the widget should calculate how big it want's to be");
+SIGNAL("size_allocate", "Called when the widget get's the size it should be");
+SIGNAL("state_changed", "");
+SIGNAL("parent_set", "Called when the parent widget is changed");
+SIGNAL("style_set", "Called when the style is changed");
+SIGNAL("event", "Called for all events");
+SIGNAL("button_press_event", "Called when a mouse button is pressed");
+SIGNAL("button_release_event", "Called when a mouse button is released");
+SIGNAL("motion_notify_event", "Called when the mouse is moved inside the widget");
+SIGNAL("delete_event",  "Called when the user has requested that the widget should be closed");
+SIGNAL("destroy_event", "Called when the widget is destroyed");
+SIGNAL("expose_event",  "Called when the widget, or a part of the widget gets and expose event");
+SIGNAL("key_press_event", "Called when a keyboard key is pressed");
+SIGNAL("key_release_event", "Called when a keyboard key is released");
+SIGNAL("enter_notify_event", "Called when the mouse enters the widget");
+SIGNAL("leave_notify_event", "Called when the mouse leaves the widget");
+SIGNAL("configure_event", "The size, position or stacking order of the widget has changed");
+SIGNAL("focus_in_event", "The keyboard focus has entered the widget");
+SIGNAL("focus_out_event", "The keyboard focus has left the widget");
+SIGNAL("map_event", "Called just before the 'map' signal");
+SIGNAL("unmap_event", "Called just before the 'unmap' signal");
+SIGNAL("property_notify_event", "Called when a property of the GDK window associated with the widget is changed");
+SIGNAL("selection_clear_event", "NYI");
+SIGNAL("selection_request_event", "NYI");
+SIGNAL("selection_notify_event", "NYI");
+SIGNAL("selection_received", "NYI");
+SIGNAL("proximity_in_event", "");
+SIGNAL("proximity_out_event", "");
+SIGNAL("drag_leave", "Called when the mouse leaves the widget while the user is dragging something");
+SIGNAL("drag_begin", "Called when the drag is initiated, on the sending side");
+SIGNAL("drag_end", "Called when the drag is finished, on the sending side");
+SIGNAL("drag_data_delete", "Called when the data can be safely deleted (there is no need to use this function in pigtk, it's all handled automatically)");
+SIGNAL("drag_motion", "Called on the receiving side when the cursor is moved over the widget while dragging something");
+SIGNAL("drag_drop", "Called on the receiving side when the drop is initiated");
+SIGNAL("drag_data_get", "Called on the sending side when the drop is initiated");
+SIGNAL("drag_data_received", "Called on the receiving side when the drop is finished.");
+SIGNAL("visibility_notify_event", "The widget has been mapped, unmapped, hidden, or otherwise had it's visibility modified");
+SIGNAL("debug_msg", "");
+SIGNAL("other_event", "");
+SIGNAL("client_event", "An event sent by another client application");
+SIGNAL("no_expose_event", "");
+
+INHERIT(object);
+/*  TODO: Some 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.
+// <br>NOTE: The widget must be realized before this function can be used
+{
+  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(GTK.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. 
+// <br>NOTE: The widget must be realized before this function can be used
+{
+  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( TWIN, GC(gc), xd, yd, win, xs, ys, w, h);
+  RETURN_THIS();
+}
+
+FUNCTION(get_gdkwindow, "function(void:object)");
+RETURNS(GDK.Window);
+// Return the GDK.Window associated with this widget, if any.
+{
+  pop_n_elems(args);
+  if(GTK_WIDGET(THIS->obj)->window)
+  {
+    struct object *o;
+    o = low_clone( pgtk_GdkWindow_program );
+    call_c_initializers( o );
+    /* ugly...*/
+    ((struct object_wrapper *)o->storage)->obj=
+      (void *)&GTK_WIDGET(THIS->obj)->window;
+    ref_push_object( o );
+  } else
+    push_int(0);
+}
+
+
+FUNCTION(shape_combine_mask, "function(object,int,int:object)");
+RETURNS(GTK.Widget);
+ARGS(GDK.Bitmap,int,int);
+NAME_ARGS(shape, 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"))->shape_combine_mask( GDK.Bitmap(Image.image(100,100,255,255,255)->rotate(10,0,0,0) ), 20,20)
+// <br>NOTE: The widget must be realized before this function can be used
+{
+  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)");
+// Returns ([ "x":xoffset, "y":yoffset, "width":xsize, "height":ysize ])
+{
+  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, group, key, modifiers, flags);
+// Add an accelerator (keyboard shortcut).
+// <p>
+// Flag is one of CONST(GTK_ACCE)
+// <br>
+// The signal is the signal to invoke when the accelerator key is pressed.
+// <br>
+// The modifiers is a bitwise or of one or more of GDK.ShiftMask,
+// GDK.LockMask, GDK.ControlMask, CONST(GDK_MOD).
+// <br>
+// The group is the accelerator group in which the accelerator should be added.
+// <br>
+// The key is the unicode code for the key to bind.
+
+COMPLEX_FUNCTION(remove_accelerator, accel_group, int, int);
+NAME_ARGS(group,key,modifiers);
+// Remove an accelerator (keyboard shortcut).
+// <p>
+// The modifiers is a bitwise or of one or more of GDK.ShiftMask,
+// GDK.LockMask, GDK.ControlMask, CONST(GDK_MOD).
+// <br>
+// The group is the accelerator group in which the accelerator should be added.
+// <br>
+// The key is the unicode code for the key to bind.
+
+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. 0 for any size means
+// 'keep old size'. When setting sizes of wtoplevel windows, it is 
+// preferable to use set_default_size
+
+COMPLEX_FUNCTION(set_uposition, int, int);
+NAME_ARGS(xpos,ypos);
+// Set the absolute coordinates of the widget relative to it's parent.
+
+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).
+// This function should normaly not be used directly.
+
+COMPLEX_FUNCTION(set_sensitive, int);
+NAME_ARGS(sensitivep);
+// True (1) or false (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,void|object,void|object:object)");
+ARGS(int|void,void|GDK.Color,void|GDK.Color);
+NAME_ARGS(cursor_type, fg, bg);
+// Change the widget cursor.<br>
+// If no arguments are passed, restore the default cursor.<br>
+// Both fg and bg must be specified if either one is.<br>
+// <table border=0 cellpadding=3 cellspacing=0>
+// CURS(GDK.Arrow)
+// CURS(GDK.BasedArrowDown)
+// CURS(GDK.BasedArrowUp)
+// CURS(GDK.Boat)
+// CURS(GDK.Bogosity)
+// CURS(GDK.BottomLeftCorner)
+// CURS(GDK.BottomRightCorner)
+// CURS(GDK.BottomSide)
+// CURS(GDK.BottomTee)
+// CURS(GDK.BoxSpiral)
+// CURS(GDK.CenterPtr)
+// CURS(GDK.Circle)
+// CURS(GDK.Clock)
+// CURS(GDK.CoffeeMug)
+// CURS(GDK.Cross)
+// CURS(GDK.CrossReverse)
+// CURS(GDK.Crosshair)
+// CURS(GDK.DiamondCross)
+// CURS(GDK.Dot)
+// CURS(GDK.Dotbox)
+// CURS(GDK.DoubleArrow)
+// CURS(GDK.DraftLarge)
+// CURS(GDK.DraftSmall)
+// CURS(GDK.DrapedBox)
+// CURS(GDK.Exchange)
+// CURS(GDK.Fleur)
+// CURS(GDK.Gobbler)
+// CURS(GDK.Gumby)
+// CURS(GDK.Hand1)
+// CURS(GDK.Hand2)
+// CURS(GDK.Heart)
+// CURS(GDK.Icon)
+// CURS(GDK.IronCross)
+// CURS(GDK.LeftPtr)
+// CURS(GDK.LeftSide)
+// CURS(GDK.LeftTee)
+// CURS(GDK.Leftbutton)
+// CURS(GDK.LlAngle)
+// CURS(GDK.LrAngle)
+// CURS(GDK.Man)
+// CURS(GDK.Middlebutton)
+// CURS(GDK.Mouse)
+// CURS(GDK.Pencil)
+// CURS(GDK.Pirate)
+// CURS(GDK.Plus)
+// CURS(GDK.QuestionArrow)
+// CURS(GDK.RightPtr)
+// CURS(GDK.RightSide)
+// CURS(GDK.RightTee)
+// CURS(GDK.Rightbutton)
+// CURS(GDK.RtlLogo)
+// CURS(GDK.Sailboat)
+// CURS(GDK.SbDownArrow)
+// CURS(GDK.SbHDoubleArrow)
+// CURS(GDK.SbLeftArrow)
+// CURS(GDK.SbRightArrow)
+// CURS(GDK.SbUpArrow)
+// CURS(GDK.SbVDoubleArrow)
+// CURS(GDK.Shuttle)
+// CURS(GDK.Sizing)
+// CURS(GDK.Spider)
+// CURS(GDK.Spraycan)
+// CURS(GDK.Star)
+// CURS(GDK.Target)
+// CURS(GDK.Tcross)
+// CURS(GDK.TopLeftArrow)
+// CURS(GDK.TopLeftCorner)
+// CURS(GDK.TopRightCorner)
+// CURS(GDK.TopSide)
+// CURS(GDK.TopTee)
+// CURS(GDK.Trek)
+// CURS(GDK.UlAngle)
+// CURS(GDK.Umbrella)
+// CURS(GDK.UrAngle)
+// CURS(GDK.Watch)
+// CURS(GDK.Xterm)
+// </table>
+{
+  GdkCursor *c;
+  struct object *fg = NULL, *bg = NULL;
+  int i;
+
+  if(!args)
+    i = -1;
+  else if( args >= 3 )
+    get_all_args("set_cursor", args, "%d%o%o", &i, &fg, &bg);
+  else
+    get_all_args("set_cursor", args, "%d", &i);
+
+  if(i>255) 
+    error("No such cursor\n");
+  if( i >= 0 )
+    c = gdk_cursor_new( i );
+  else
+    c = NULL;
+
+#ifndef __NT__
+  if( c && fg && bg )
+  {
+    XColor fgp, bgp;
+    MEMSET(&fgp, 0, sizeof(fg) );
+    MEMSET(&bgp, 0, sizeof(bg) );
+
+    if( get_gdkobject( fg, Color ) )
+      fgp.pixel = ((GdkColor *)get_gdkobject( fg, Color ))->pixel;
+    if( get_gdkobject( bg, Color ) )
+      bgp.pixel = ((GdkColor *)get_gdkobject( bg, Color ))->pixel;
+    
+    XRecolorCursor(((GdkCursorPrivate *)c)->xdisplay,
+                   ((GdkCursorPrivate *)c)->xcursor,
+                   &fgp, &bgp );
+  }
+#endif  
+  gtk_object_set_data_full(THIS->obj,
+                           "cursor_to_free",(void*)c,
+                           (void*)gdk_cursor_destroy);
+  gdk_window_set_cursor( TWIN, 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 and yhot are the locations of the x and y hotspot relative to the
+// upper left corner of the cursor image.
+// Both bitmaps and both colors must be non-null.
+{
+  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( TWIN,
+		 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);
+// Remove this widget from it's parent
+SIMPLE_FUNCTION(realize);
+// Realize this widget, and it's children, if nessesary
+SIMPLE_FUNCTION(unrealize);
+// Unrealize this widget, and it's children, if nessesary
+SIMPLE_FUNCTION(queue_draw);
+// Force a redraw of the widget
+COMPLEX_FUNCTION(queue_draw_area, int,int,int,int);
+NAME_ARGS(x,y,width,height);
+// Force a redraw of part of the widget
+SIMPLE_FUNCTION(queue_clear);
+// Force a clear (and subsequent redraw) of the widget
+COMPLEX_FUNCTION(queue_clear_area, int,int,int,int);
+NAME_ARGS(x,y,width,height);
+// Force a clear (and subsequent redraw) of part of the widget
+SIMPLE_FUNCTION(ensure_style);
+// Ensure that the widget has a style associated with it.
+SIMPLE_FUNCTION(queue_resize);
+// Force a allocation recalculation, followed by a redraw
+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 it's children
+SIMPLE_FUNCTION(hide_all);
+// Hide this widget and all it's children
+SIMPLE_FUNCTION(map);
+// Map the widget. Should normally not be called directly.
+SIMPLE_FUNCTION(unmap);
+// Unmap the widget. Should normally not be called directly.
+SIMPLE_FUNCTION(activate);
+// Activate the widget. This either activates the widget, if possible
+// (as an example, buttons can be activated), or activates the default
+// widget of it's parent (or it's parent, or it's parents parent
+// etc.)
+
+SIMPLE_FUNCTION(grab_focus);
+// Grab the focus.
+SIMPLE_FUNCTION(grab_default);
+// Make this widget the default action for the parent widget
+int COMPLEX_FUNCTION(intersect, GdkRectangle, GdkRectangle);
+NAME_ARGS(area, intersection);
+// Do an intersection with the area and place the result in
+// 'intersection'.
+
+COMPLEX_FUNCTION(reparent, widget);
+NAME_ARGS(to);
+// Change the parent of the widget.
+COMPLEX_FUNCTION(popup, int,int);
+NAME_ARGS(xpos,ypos);
+// Map the widget at the specified coordinates.
+
+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);
+// return the toplevel widget this widget is inside (or this widget if
+// it is the toplevel widget)
+
+int COMPLEX_FUNCTION(get_events);
+// Return the current event mask (see set_events and add_events)
+
+int COMPLEX_FUNCTION(is_ancestor, widget);
+NAME_ARGS(of);
+// Returns true if the specified widget is an ancestor of this widget.
+ 
+Style COMPLEX_FUNCTION(get_style);
+// Return the style associated with this widget
+
+COMPLEX_FUNCTION(restore_default_style);
+// Reset all styles to their default value
+COMPLEX_FUNCTION(reset_rc_styles);
+// Reset all styles to their default value, recursively
+COMPLEX_FUNCTION(set_composite_name, string);
+NAME_ARGS(name);
+// Like set name, but it is inherited by the children of this widget.
+string COMPLEX_FUNCTION(get_composite_name);
+// Like set name, but it is inherited by the children of this widget.
+
+FUNCTION(path, "function(void:string)");
+// Returns the 'pathname' of this widget. Useful for rc-files and such.
+{
+  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)");
+// Returns the class 'pathname' of this widget. Useful for rc-files and such.
+{
+  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);
+// Make it impossible to add new accelerators, or remove old ones
+COMPLEX_FUNCTION(unlock_accelerators);
+// Make it possible to add new accelerators, and remove old ones,
+// again. Use this after lock_accelerators()
+
+int COMPLEX_FUNCTION(set_scroll_adjustments, adjustment, adjustment);
+NAME_ARGS(hadjustment,vadjustment);
+// Set the scrolling (panning) adjustment objects for this widget.
+// Returns 1 if it is possible to do so, and 0 otherwise.
+
+COMPLEX_FUNCTION(set_app_paintable, int);
+NAME_ARGS(paintablep);
+// Make it possible to draw directly in the widget using the low-level
+// drawing functions.
+
+
+FUNCTION(set_flags, "function(int:object)");
+NAME_ARGS(flags);
+// The flags that it makes sense to set are:
+// GTK.CanFocus and GTK.CanDefault
+RETURNS(GTK.Widget);
+{
+  GTK_WIDGET_SET_FLAGS( GTK_WIDGET( THIS->obj ), sp[-1].u.integer );
+  RETURN_THIS();
+}
+
+FUNCTION(unset_flags, "function(int:object)");
+NAME_ARGS(flags);
+// The flags that it makes sense to unset are:
+// GTK.CanFocus and GTK.CanDefault
+RETURNS(GTK.Widget);
+{
+  GTK_WIDGET_UNSET_FLAGS( GTK_WIDGET( THIS->obj ), sp[-1].u.integer );
+  RETURN_THIS();
+}
+
+FUNCTION(has_set_flags, "function(int:object)");
+NAME_ARGS(mask);
+// All possible flags are:
+// GTK.AppPaintable,
+// GTK.CanDefault,
+// GTK.CanFocus,
+// GTK.CompositeChild,
+// GTK.HasDefault,
+// GTK.HasFocus,
+// GTK.HasGrab,
+// GTK.Mapped,
+// GTK.NoReparent,
+// GTK.NoWindow,
+// GTK.ParentSensitive,
+// GTK.RcStyle,
+// GTK.Realized,
+// GTK.ReceivesDefault
+// GTK.Sensitive,
+// GTK.Toplevel and
+// GTK.Visible.
+RETURNS(GTK.Widget);
+{
+  pop_n_elems(args);
+  push_int( GTK_WIDGET_FLAGS(GTK_WIDGET(THIS->obj)) | sp[-1].u.integer );
+}
+
+
+
+/* DND */
+
+FUNCTION(drag_dest_unset, "function(void:object)");
+// Removes the drop support from this widget (see drag_dest_set)
+RETURNS(GTK.Widget);
+{
+  gtk_drag_dest_unset( GTK_WIDGET( THIS->obj ) );
+  RETURN_THIS();
+}
+
+FUNCTION(drag_highlight, "function(void:object)");
+// Highlight the widget. Not normaly used directly.
+RETURNS(GTK.Widget);
+{
+  gtk_drag_highlight( GTK_WIDGET( THIS->obj ) );
+  RETURN_THIS();
+}
+
+FUNCTION(drag_unhighlight, "function(void:object)");
+// Unhighlight the widget. Not normaly used directly.
+RETURNS(GTK.Widget);
+{
+  gtk_drag_unhighlight( GTK_WIDGET( THIS->obj ) );
+  RETURN_THIS();
+}
+
+FUNCTION(drag_dest_set, "function(int,array(array(int|string)),int:object)");
+NAME_ARGS(flags,targets,actions);
+//     Register a drop site, and possibly add default behaviors.<br>
+//   arguments:<br>
+//     flags:     Which types of default drag behavior to use (one of CONST(GTK_DEST_DEFAULT))<br>
+//     targets:   Table of targets that can be accepted
+//            ({ ({ content_type(string), flags(int(try 0)), id(int) }), ...})
+//       The id will be received in the signal handlers.<br>
+//     actions:   one of CONST(GDK_ACTION_)
+//   results:
+RETURNS(GTK.Widget);
+{
+  int i, f, j;
+  struct array *a;
+  GtkTargetEntry *entries = NULL;
+  get_all_args( "drag_dest_set", args, "%d%a%d", &i, &a, &f );
+  if(a->size)
+//     error("You must accept at least one target type\n");
+    entries = malloc(sizeof(GtkTargetEntry)*a->size);
+  
+  for(j=0; j<a->size; j++)
+  {
+    if(a->item[j].type != T_ARRAY || 
+       a->item[j].u.array->size != 3 ||
+       a->item[j].u.array->item[0].type != T_STRING ||
+       a->item[j].u.array->item[0].u.string->size_shift > 1 ||
+       a->item[j].u.array->item[1].type != T_INT ||
+       a->item[j].u.array->item[2].type != T_INT)
+    {
+      free(entries);
+      error("The array is malformed.\n"); 
+    }
+    entries[j].target = a->item[j].u.array->item[0].u.string->str;
+    entries[j].flags = a->item[j].u.array->item[1].u.integer;
+    entries[j].info = a->item[j].u.array->item[2].u.integer;
+  }
+  gtk_drag_dest_set( GTK_WIDGET( THIS->obj ), i, entries, a->size, f);
+  if(entries)
+    free(entries);
+  RETURN_THIS();
+}
+
+
+
+FUNCTION(drag_source_set, "function(int,array(array(int|string)),int:object)");
+NAME_ARGS(flags,targets,actions);
+//     Register a drop site, and possibly add default behaviors.<br>
+//   arguments:<br>
+//     buttons:     Which mouse buttons can be used to start the drag<br>
+//     targets:   Table of targets that can be accepted
+//            ({ ({ content_type(string), flags(int(try 0)), id(int) }), ...})
+//       The id will be received in the signal handlers.<br>
+//     actions:   one of CONST(GDK_ACTION_)
+//   results:
+RETURNS(GTK.Widget);
+{
+  int i, f, j;
+  struct array *a;
+  GtkTargetEntry *entries = NULL;
+  get_all_args( "drag_source_set", args, "%d%a%d", &i, &a, &f );
+
+  if(a->size)
+//     error("You must provide at least one target type\n");
+    entries = malloc(sizeof(GtkTargetEntry)*a->size);
+  
+  for(j=0; j<a->size; j++)
+  {
+    if(a->item[j].type != T_ARRAY || 
+       a->item[j].u.array->size != 3 ||
+       a->item[j].u.array->item[0].type != T_STRING ||
+       a->item[j].u.array->item[0].u.string->size_shift > 1 ||
+       a->item[j].u.array->item[1].type != T_INT ||
+       a->item[j].u.array->item[2].type != T_INT)
+    {
+      free(entries);
+      error("The array is malformed.\n"); 
+    }
+    entries[j].target = a->item[j].u.array->item[0].u.string->str;
+    entries[j].flags = a->item[j].u.array->item[1].u.integer;
+    entries[j].info = a->item[j].u.array->item[2].u.integer;
+  }
+  gtk_drag_source_set( GTK_WIDGET( THIS->obj ), i, entries, a->size, f);
+  if(entries)
+    free(entries);
+  RETURN_THIS();
+}
+
+FUNCTION(drag_source_unset, "function(void:object)");
+// Remove the drag support from this widget. See drag_source_set.
+RETURNS(GTK.Widget);
+{
+  gtk_drag_source_unset( GTK_WIDGET( THIS->obj ) );
+  RETURN_THIS();
+}
+
+FUNCTION(drag_source_set_icon, "function(object,object:object)");
+// Set the icon that will be used (by default) for drags
+// from this widget.
+RETURNS(GTK.Widget);
+ARGS(GDK.Pixmap,GDK.Bitmap);
+NAME_ARGS(image,mask);
+{
+  struct object *p=NULL, *m=NULL;
+  if(args == 2)
+  {
+    if(sp[-args].type == T_OBJECT)
+      p = sp[-args].u.object;
+    if(sp[-args+1].type == T_OBJECT)
+      m = sp[-args+1].u.object;
+  }  else {
+    if(sp[-args].type == T_OBJECT)
+      p = sp[-args].u.object;
+  }
+  gtk_drag_source_set_icon( GTK_WIDGET( THIS->obj ),
+                            gdk_colormap_get_system(),
+                            get_gdkobject( p, Pixmap ),
+                            get_gdkobject( m, Bitmap ));
+  RETURN_THIS();
+}
+
+
+FUNCTION(drag_get_data, "function(object,int:object)");
+// Get the data from a context and an integer timestamp, requesting
+// it from the dropping client. This will probably never be used
+// directly.<p>
+//
+// Use the selection argument passed to the drag_data_received signal
+// instead.
+RETURNS(GTK.Widget);
+ARGS(GDK.DragContext,int);
+NAME_ARGS(context,time);
+{
+  int t;
+  struct object *_ctx;
+  GdkDragContext *ctx;
+  get_all_args( "drag_get_data", args, "%o%d", &_ctx, &t );
+  ctx = (GdkDragContext *)get_gdkobject( _ctx, DragContext );
+  if(ctx && ctx->targets)
+    gtk_drag_get_data( GTK_WIDGET( THIS->obj ), ctx, 
+                       GPOINTER_TO_INT( ctx->targets->data ),
+                       t );
+}
diff --git a/src/post_modules/GTK/source/gtkwindow.pre b/src/post_modules/GTK/source/gtkwindow.pre
new file mode 100644
index 0000000000000000000000000000000000000000..c3ba696bf10c805299056d79f80ace067e443238
--- /dev/null
+++ b/src/post_modules/GTK/source/gtkwindow.pre
@@ -0,0 +1,156 @@
+PROGRAM(window);
+// The basic window. Nothing much to say about it. It can only contain
+// one child widget. Show the main window last to avoid annoying
+// flashes when the subwidet (and it's subwidgets) are added to it,
+// this is done automatically by calling 'window->show_all' when you
+// are done with your widget packing.
+SIGNAL("move_resize", "");
+SIGNAL("set_focus", "");
+INHERIT(bin);
+
+COMPLEX_FUNCTION(create, int);
+NAME_ARGS(window_type);
+// Argument is one of CONST(GTK_WINDOW)
+COMPLEX_FUNCTION(set_wmclass, string, string);
+NAME_ARGS(name,class);
+// Set the window manager application name and class.
+COMPLEX_FUNCTION(set_title, string);
+NAME_ARGS(title);
+// Set the window title. The default title is the value sent to
+// setup_gtk, or if none is sent, Pike GTK.
+COMPLEX_FUNCTION(set_focus, widget);
+NAME_ARGS(child);
+// Set the focus widget to the specified child. Please note that this
+// is normaly handled automatically.
+int COMPLEX_FUNCTION(activate_focus);
+// Activate the focus widget
+int COMPLEX_FUNCTION(activate_default);
+// Activate the default widget
+COMPLEX_FUNCTION(add_accel_group, accel_group);
+NAME_ARGS(group);
+// This function adds an accelerator group to the window. The shortcuts in
+// the table will work in the window, it's child, and all children of
+// it's child that do not select keyboard input.
+
+COMPLEX_FUNCTION(set_transient_for, window);
+NAME_ARGS(parent);
+// Mark this window as a transient window for the parent window.
+// Most window managers renders transient windows differently (different
+// borders, sometimes no resize widgets etc)
+// <p>
+// Useful for short lived dialogs.
+COMPLEX_FUNCTION(set_default_size, int,int);
+NAME_ARGS(width,height);
+// The following differs from set_usize, in that
+// set_usize() overrides the requisition, and thus sets a minimum
+// size, while this only sets the size requested from the WM.
+COMPLEX_FUNCTION(set_modal, int);
+NAME_ARGS(modalp);
+/// Is this a modal dialog?
+
+COMPLEX_FUNCTION(remove_embedded_xid, int);
+NAME_ARGS(x_window_id);
+// Remove the embeded X window
+COMPLEX_FUNCTION(add_embedded_xid, int);
+NAME_ARGS(x_window_id);
+// Add an embedded X-window
+
+COMPLEX_FUNCTION(remove_accel_group, accel_group);
+NAME_ARGS(table);
+// Remove a previously installed table.
+COMPLEX_FUNCTION(set_default, widget);
+NAME_ARGS(default_widget);
+// Set the default widget to the specified widget.
+// The specified widget <b>must</b> have the GTK.CanDefault flag set.
+COMPLEX_FUNCTION(set_position, int);
+NAME_ARGS(pos);
+// one of CONST(GTK_WIN)
+COMPLEX_FUNCTION(set_policy, int,int,int);
+NAME_ARGS(allow_shrink,allow_grow,auto_shrink);
+// If allow shrink is true, the user can resize the window to a
+// smaller size. If allow_grow is true, the window can resize itself,
+// and the user can resize the window, to a bigger size. It auto
+// shrink is true, the window will resize itself to a smaller size
+// when it's subwidget is resized.
+
+FUNCTION(raise, "function(void:object)");
+RETURNS(GTK.Window);
+// Raise this window if the window manager allows that.
+{
+  gdk_window_raise( GTK_WIDGET( THIS->obj )->window );
+  RETURN_THIS();
+}
+
+FUNCTION(lower, "function(void:object)")
+RETURNS(GTK.Window);
+// Lower this window if the window manager allows that.
+{
+  gdk_window_lower( GTK_WIDGET( THIS->obj )->window );
+  RETURN_THIS();
+}
+
+FUNCTION(set_icon_name, "function(string:object)")
+NAME_ARGS(icon_name);
+RETURNS(GTK.Window);
+// Set the icon name to the specified string.
+{
+  gchar *t;
+  get_all_args("set_icon_name", args, "%s", &t);
+  gdk_window_set_icon_name( GTK_WIDGET(THIS->obj)->window, t );
+  RETURN_THIS();
+}
+
+FUNCTION(set_icon, "function(object|void,object|void,object|void:object)");
+RETURNS(GDK.Window);
+NAME_ARGS(window,pixmap,mask);
+ARGS(GDK.Pixmap,GDK.Bitmap,GDK.Window);
+// Set the icon to the specified image (with mask) or the specified GDK.Window.
+// It is up to the window manager to display the icon.
+// Most window manager handles window and pixmap icons, but only a few
+// can handle the mask argument. If you want a shaped icon, the only
+// safe bet is a shaped window.
+{
+  GdkPixmap *p = NULL;
+  GdkBitmap *m = NULL;
+  GdkWindow *w = NULL;
+  switch(args)
+  {
+   default:
+   case 3:
+     if(sp[-args+2].type == T_OBJECT)
+       w = get_gdkobject(sp[-args+2].u.object , Window );
+   case 2:
+     if(sp[-args+1].type == T_OBJECT)
+       m = get_gdkobject(sp[-args+1].u.object , Bitmap );
+   case 1:
+     if(sp[-args].type == T_OBJECT)
+       p = get_gdkobject(sp[-args].u.object , Pixmap );
+  }
+  gdk_window_set_icon(GTK_WIDGET(THIS->obj)->window, w, p, m );
+  RETURN_THIS();
+}
+
+CLASSMEMBER(modal, int);
+// If true, this is a modal dialog window
+CLASSMEMBER(auto_shrink, int);
+// If true, the window will shrink if possible
+CLASSMEMBER(allow_shrink, int);
+// If true, the window can be shrunk by the user
+CLASSMEMBER(allow_grow, int);
+// If true, the window can grow if nessesary
+CLASSMEMBER(type, int);
+// The window type, one of CONST(GTK_WINDOW)
+
+CLASSMEMBER(wmclass_name, string);
+// The window manager name of this application.
+CLASSMEMBER(wmclass_class, string);
+// The window manager class of this application.
+CLASSMEMBER(title, string);
+// The title of the window
+SUBWIDGET(focus_widget, widget);
+// The focus widget
+SUBWIDGET(default_widget, widget);
+// The default widget
+SUBWIDGET(transient_parent, window);
+// The parent window for this window if this is a transient window, 0
+// otherwise.
diff --git a/src/post_modules/GTK/source/support.c b/src/post_modules/GTK/source/support.c
new file mode 100644
index 0000000000000000000000000000000000000000..a72e0131208ee7c71b44db8433cb5aecc8ac2c86
--- /dev/null
+++ b/src/post_modules/GTK/source/support.c
@@ -0,0 +1,828 @@
+#include <version.h>
+
+struct image;
+void pgtk_encode_truecolor_masks(struct image *i,
+                                 int bitspp,
+                                 int pad,
+                                 int byteorder,
+                                 unsigned int red_mask,
+                                 unsigned int green_mask,
+                                 unsigned int blue_mask,
+                                 unsigned char *buffer, 
+                                 int debuglen);
+
+
+typedef struct 
+{
+   unsigned char r,g,b;
+} p_rgb_group;
+
+typedef struct
+{
+   INT32 r,g,b;
+} p_rgbl_group;
+
+
+struct p_color_struct
+{
+   p_rgb_group rgb;
+   p_rgbl_group rgbl;
+   struct pike_string *name;
+};
+
+void pgtk_get_image_module()
+{
+  push_constant_text("Image"); 
+  push_int(0);
+  SAFE_APPLY_MASTER("resolv", 2);
+  if (sp[-1].type!=T_OBJECT) error("No Image module.\n");
+}
+
+void pgtk_index_stack( char *what )
+{
+  push_text(what);
+  f_index(2);
+#ifdef DEBUG
+  if (sp[-1].type==T_INT)
+    error("Internal indexing error.\n");
+#endif
+}
+
+#define COLORLMAX 0x7fffffff
+int get_color_from_pikecolor( struct object *o, int *r, int *g, int *b )
+{
+  struct p_color_struct *col;
+  static struct program *pike_color_program;
+  if(!pike_color_program)
+  {
+    pgtk_get_image_module();
+    pgtk_index_stack( "Color" );
+    pgtk_index_stack( "Color" );
+    pike_color_program = program_from_svalue(--sp);
+  }
+  
+  col = (struct p_color_struct *)get_storage( o, pike_color_program );
+  if(!col) return 0;
+  *r = col->rgbl.r/(COLORLMAX/65535);
+  *g = col->rgbl.g/(COLORLMAX/65535);
+  *b = col->rgbl.b/(COLORLMAX/65535);
+  return 1;
+}
+
+
+
+void pgtk_encode_grey(struct image *i, unsigned char *dest, int bpp, int bpl );
+
+void *get_swapped_string( struct pike_string *s,int force_wide )
+{
+  int i;
+  unsigned short *res, *tmp;
+#if (BYTEORDER!=4321)
+  switch(s->size_shift)
+  {
+   default:
+     return 0;
+   case 1:
+     {
+       res= malloc(s->len * 2);
+       tmp = (unsigned short *)s->str;
+       for(i=0;i<s->len; i++)
+	 res[i] = htons( tmp[i] );
+       return res;
+     }
+  }
+#endif
+  if(force_wide)
+  {
+    switch(s->size_shift)
+    {
+     case 0:
+       res = malloc(s->len*2);
+       for(i=0;i<s->len;i++)
+	 res[i] = htons( (short)(((unsigned char *)s->str)[i]) );
+       return res;
+     case 1: 
+       return 0;
+     case 2:
+       res = malloc(s->len*2);
+       for(i=0;i<s->len;i++)
+	 res[i] = htons( (short)(((unsigned int *)s->str)[i]) );
+       return res;
+    }
+  }
+#ifdef DEBUG
+  fatal("not reached\n");
+#endif
+  return 0;
+}
+
+struct object *pikeimage_from_gdkimage( GdkImage *img )
+{
+}
+
+
+
+GdkImage *gdkimage_from_pikeimage( struct object *img, int fast, GdkImage *i )
+{
+  GdkColormap *col = gdk_colormap_get_system();
+  GdkVisual *vis = gdk_visual_get_system();
+  int x, y;
+
+  /* 1a: create the actual image... */
+  TIMER_INIT("Getting extents");
+  apply(img, "xsize", 0); apply(img, "ysize", 0);
+  get_all_args("internal", 2, "%d%d", &x, &y);
+  pop_n_elems( 2 );
+
+
+  if( x==0 || y==0 )
+    error("Size of image must be > 0x0\n");
+  if(i)
+  {
+    if((i->width != x) || (i->height != y))
+    {
+/*       fprintf(stderr, "New %s%dx%d image\n", (fast?"fast ":""), x, y); */
+      gdk_image_destroy((void *)i);
+      i = NULL;
+    }
+  }
+  if(!i)
+  {
+    PFTIME("Create");
+    i = (void *)gdk_image_new(fast, vis, x, y);
+  }
+
+  if(!i)
+    error("Failed to create gdkimage\n");
+
+  /* 1b: do the work.. */
+
+  if(vis->type == GDK_VISUAL_TRUE_COLOR || vis->type == GDK_VISUAL_STATIC_GRAY)
+    /* no colormap.. */
+  {
+    int pad = 0;
+    int native_byteorder;
+    PFTIME("Convert");
+
+    if(vis->type == GDK_VISUAL_STATIC_GRAY)
+      pgtk_encode_grey( (void *)img->storage, i->mem, i->bpp, i->bpl );
+    else
+    {
+      switch(i->bpl - (i->bpp*x))
+      {
+       case  0: pad = 0; break;
+       case  1: pad = 2; break;
+       default: pad = 4; break;
+      }
+      pgtk_encode_truecolor_masks( (void *)img->storage, i->bpp*8, pad*8, 
+                                   (i->byte_order!=MSBFirst), vis->red_mask, 
+                                   vis->green_mask, vis->blue_mask,
+                                   i->mem, i->bpl*y );
+    }
+  } else {
+    static int colors_allocated = 0;
+    static struct object *pike_cmap;
+    /* I hate this... colormaps, here we come.. */
+    /* This is rather complicated, but: 
+       1/ build an array of the colors in the colormap
+       2/ use that array to build a pike X-image colormap.
+       3/ call Image.X.encode_pseudocolor( img, bpp, lpad, depth, colormp )
+       4/ copy the actual data to the image..
+    */
+    if(!colors_allocated)
+    {
+#define COLORMAP_SIZE 256
+      char allocated[COLORMAP_SIZE];
+      int j, i, r, g, b;
+      PFTIME("Creating colormap");
+      colors_allocated=1;
+      MEMSET(allocated, 0, sizeof(allocated));
+      for(r=0; r<3; r++) for(g=0; g<4; g++) for(b=0; b<3; b++)
+      {
+	GdkColor color;
+	color.red = (int)(r * (65535/2.0));
+	color.green = (int)(g * (65535/3.0));
+	color.blue = (int)(b * (65535/2.0));
+	color.pixel = 0;
+	if(gdk_color_alloc( col, &color ))
+          if(color.pixel < COLORMAP_SIZE)
+            allocated[ color.pixel ] = 1;
+      }
+      for(r=0; r<6; r++) for(g=0; g<7; g++) for(b=0; b<6; b++)
+      {
+	GdkColor color;
+	color.red = (int)(r * (65535/5.0));
+	color.green = (int)(g * (65535/6.0));
+	color.blue = (int)(b * (65535/5.0));
+	color.pixel = 0;
+	if(gdk_color_alloc( col, &color ))
+          if(color.pixel < COLORMAP_SIZE)
+            allocated[ color.pixel ] = 1;
+      }
+      
+      for(i=0; i<COLORMAP_SIZE; i++)
+      {
+	if( allocated[ i ] )
+	{
+	  push_int(col->colors[i].red>>8);
+	  push_int(col->colors[i].green>>8);
+	  push_int(col->colors[i].blue>>8);
+	  f_aggregate(3);
+	}
+	else
+	  push_int(0);
+      }
+      f_aggregate(256);
+      /* now on stack: the array with colors. */
+      pgtk_get_image_module();
+      pgtk_index_stack("colortable");
+      /* on stack: array function */
+      sp[0]=sp[-1];
+      sp[-1]=sp[-2];
+      sp[-2]=sp[0];
+      /* on stack: function array */
+      PFTIME("Creating colormap obj");
+      apply_svalue( sp-2, 1 );
+      /* on stack: function cmap */
+      get_all_args("internal", 1, "%o", &pike_cmap);
+      pike_cmap->refs+=100; /* lets keep this one.. :-) */
+      push_int(8); push_int(8); push_int(8);
+#if (PIKE_MAJOR_VERSION > 0) || (PIKE_MINOR_VERSION > 6)
+      apply(pike_cmap, "rigid", 3);       pop_stack();
+#else
+      apply(pike_cmap, "cubicles", 3);    pop_stack();
+#endif
+      apply(pike_cmap, "ordered", 0);    pop_stack(); 
+      pop_stack();
+    }
+    
+    { /* now we have a colormap available. Happy happy joy joy! */
+      struct pike_string *s;
+      pgtk_get_image_module();
+      pgtk_index_stack( "X" );
+      pgtk_index_stack( "encode_pseudocolor" );
+      /* on stack: function */
+ add_ref(img);
+      push_object( img );
+      push_int( i->bpp*8 );
+      {
+	int pad = 0;
+	switch(i->bpl - (i->bpp*x))
+	{
+	 case  0: pad = 0; break;
+	 case  1: pad = 16; break;
+	 default: pad = 32; break;
+	}
+	push_int( pad  ); /* extra padding.. */
+      }
+      push_int( i->depth );
+ add_ref(pike_cmap);
+      push_object( pike_cmap );
+      /* on stack: function img bpp linepad depth cmap*/
+      /*             6       5    4  3       2     1 */
+      PFTIME("Dithering image");
+      apply_svalue( sp-6, 5 );
+      if(sp[-1].type != T_STRING)
+      {
+	gdk_image_destroy((void *)i);
+	error("Failed to convert image\n");
+      }
+      PFTIME("Converting image");
+      MEMCPY(i->mem, sp[-1].u.string->str, sp[-1].u.string->len);
+      pop_stack(); /* string */
+      pop_stack(); /* function */
+    }
+  }
+  TIMER_END();
+  return i;
+}
+
+void push_gtkobjectclass(void *obj, struct program *def)
+{
+  struct object *o;
+  if(!obj)
+  {
+    push_int(0);
+    return;
+  }
+  if( (o=gtk_object_get_data(GTK_OBJECT(obj), "pike_object")) )
+  {
+    ref_push_object( o );
+    return;
+  }
+  o = low_clone( def );
+  call_c_initializers( o );
+  ((struct object_wrapper *)o->storage)->obj = obj;
+  pgtk__init_object( o );
+  ref_push_object( o );
+  return;
+}
+
+
+void push_pgdkobject(void *obj, struct program *def)
+{
+  struct object *o;
+  if(!obj)
+  {
+    push_int(0);
+    return;
+  }
+  o = low_clone( def );
+  call_c_initializers( o );
+  ((struct object_wrapper *)o->storage)->obj = obj;
+  ref_push_object( o );
+  return;
+}
+
+GtkObject *get_pgtkobject(struct object *from, struct program *type)
+{
+  struct object_wrapper * o;
+  if(!from) return NULL; 
+  o=(struct object_wrapper *)get_storage( from, type );
+  if(!o) return 0;
+  return o->obj;
+}
+
+void *get_pgdkobject(struct object *from, struct program *type)
+{
+  void *f;
+  if(!from) return NULL;
+  if(type)
+    f = get_storage( from, type );
+  else
+    f = from->storage;
+  if(!f) 
+    return 0;
+  return (void *)((struct object_wrapper *)f)->obj;
+}
+
+
+static void adjust_refs( GtkWidget *w, void *f, void *q)
+{
+  struct object *o;
+  if( !(o=gtk_object_get_data(GTK_OBJECT(w), "pike_object")) )
+    return;
+
+  if( w->parent )
+  {
+    o->refs++;
+  }
+  else
+  {
+    free_object( o ); 
+  }
+}
+
+void my_destruct( struct object *o )
+{
+  GtkObject *go = get_gtkobject(o);
+  if(!go) return;
+  ((struct object_wrapper *)o->storage)->obj = NULL;
+/*   if( !GTK_IS_WIDGET( go ) ) */
+  free_object( o );
+}
+
+void pgtk__init_object( struct object *o )
+{
+  GtkObject *go = get_gtkobject(o);
+  if(!go)
+    fatal("pgtk__init_object called on a non-pgtk object!\n");
+
+  /* A real refcounting system.. Might work, who knows? :-) */
+/*   if( GTK_IS_WIDGET( go ) ) */
+/*     gtk_signal_connect( go, "parent_set", adjust_refs, NULL ); */
+/*   else */
+  o->refs++; 
+
+  gtk_object_set_data_full(go,"pike_object",
+			   (void*)o, (void*)my_destruct);
+}
+
+void pgtk_get_mapping_arg( struct mapping *map,
+                           char *name, int type, int madd,
+                           void *dest, long *mask, int len )
+{
+  struct svalue *s;
+  if( s = simple_mapping_string_lookup( map, name ) )
+  {
+    if( s->type == type )
+    {
+      switch(type)
+      {
+       case T_STRING:
+         if(len != sizeof(char *))
+           fatal("oddities detected\n");
+         MEMCPY(((char **)dest), &s->u.string->str, sizeof(char *));
+         break;
+       case T_INT:
+         if(len == 2)
+         {
+           short i = (short)s->u.integer;
+           MEMCPY(((short *)dest), &i, 2);
+         }
+         else if(len == 4)
+           MEMCPY(((int *)dest), &s->u.integer, len);
+         break;
+       case T_FLOAT:
+         if(len == sizeof(float))
+           MEMCPY(((float *)dest), &s->u.float_number,len);
+         else if(len == sizeof(double))
+         {
+           double d = s->u.float_number;
+           MEMCPY(((double *)dest), &d,len);
+         }
+         break;
+      }
+      *mask |= madd;
+    }
+  }
+}
+
+GdkAtom get_gdkatom( struct object *o )
+{
+  if(get_gdkobject( o,_Atom ))
+    return (GdkAtom)get_gdkobject( o, _Atom );
+  apply( o, "get_atom", 0);
+  get_all_args( "internal_get_atom", 1, "%o", &o );
+  if(get_gdkobject( o,_Atom ))
+  {
+    GdkAtom r = (GdkAtom)get_gdkobject( o,_Atom );
+    pop_stack();
+    return r;
+  }
+  error("Got non GDK.Atom object to get_gdkatom()\n");
+}
+
+
+struct my_pixel pgtk_pixel_from_xpixel( unsigned int pix, GdkImage *i )
+{
+  static GdkColormap *col;
+  GdkColor * c;
+  struct my_pixel res;
+  int l;
+  if(!col) col = gdk_colormap_get_system();
+  res.r = res.g= res.b = 0;
+  switch(i->visual->type)
+  {
+   case GDK_VISUAL_GRAYSCALE:
+   case GDK_VISUAL_PSEUDO_COLOR:
+     for(l=0; l<col->size; l++)
+       if(col->colors[l].pixel == pix) /* 76 */
+       {
+	 res.r = col->colors[l].red/257;
+	 res.g = col->colors[l].green/257;
+	 res.b = col->colors[l].blue/257;
+	 break;
+       }
+     break;
+
+   case GDK_VISUAL_STATIC_COLOR:
+   case GDK_VISUAL_TRUE_COLOR:
+   case GDK_VISUAL_DIRECT_COLOR:
+     /* Well well well.... */
+     res.r = ((pix&i->visual->red_mask) 
+	      >> i->visual->red_shift)
+	      << (8-i->visual->red_prec);
+     res.g = ((pix&i->visual->green_mask) 
+	      >> i->visual->green_shift)
+	      << (8-i->visual->green_prec);
+     res.b = ((pix&i->visual->blue_mask) 
+	      >> i->visual->blue_shift)
+	      << (8-i->visual->blue_prec);
+     break;
+   case GDK_VISUAL_STATIC_GRAY:
+     res.r = res.g = res.b = (pix*256) / 1<<i->visual->depth;
+     break;
+  }
+  return res;
+}
+
+
+int pgtkbuttonfuncwrapper(GtkObject *obj, struct signal_data *d, void *foo)
+{
+  int res;
+  push_svalue(&d->args);
+  apply_svalue(&d->cb, 1);
+  res = sp[-1].u.integer;
+  pop_stack();
+  return res;
+}
+
+void push_gdk_event(GdkEvent *e)
+{
+  struct svalue *osp = sp;
+  if(!e)
+  {
+    push_text("NullEvent"); /* Why, o why? */
+    return;
+  }
+  switch(e->type)
+  {
+   case GDK_NOTHING:
+     push_text("type");  push_text("nothing");
+     break;
+   case GDK_DELETE:
+     push_text("type");  push_text("delete");
+     break;
+   case GDK_DESTROY:
+     push_text("type");  push_text("destroy");
+     break;
+   case GDK_EXPOSE:
+     push_text("type");    push_text("expose");
+     push_text("count");   push_int(e->expose.count);
+     push_text("x");       push_int(e->expose.area.x);
+     push_text("y");       push_int(e->expose.area.y);
+     push_text("width");   push_int(e->expose.area.width);
+     push_text("height");  push_int(e->expose.area.height);
+     break;
+   case GDK_MOTION_NOTIFY:
+     push_text("type");    push_text("motion");
+     push_text("time");    push_int(e->motion.time);
+     push_text("x");       push_float(e->motion.x);
+     push_text("y");       push_float(e->motion.y);
+     push_text("pressure");push_float(e->motion.pressure);
+     push_text("xtilt");   push_float(e->motion.xtilt);
+     push_text("ytilt");   push_float(e->motion.ytilt);
+     push_text("state");   push_int(e->motion.state);
+     push_text("time");    push_int(e->motion.time);
+     push_text("deviceid");push_int(e->motion.deviceid);
+     push_text("x_root");  push_float(e->motion.x_root);
+     push_text("y_root");  push_int(e->motion.y_root);
+     break;
+
+   case GDK_BUTTON_PRESS:
+     push_text("type");    push_text("button_press");
+     goto press_event;
+   case GDK_2BUTTON_PRESS:
+     push_text("type");    push_text("2button_press");
+     goto press_event;
+   case GDK_3BUTTON_PRESS:
+     push_text("type");    push_text("3button_press");
+     goto press_event;
+   case GDK_BUTTON_RELEASE:
+     push_text("type");    push_text("button_release");
+
+  press_event:
+     push_text("time");    push_int(e->button.time);
+     push_text("x");       push_float(e->button.x);
+     push_text("y");       push_float(e->button.y);
+     push_text("pressure");push_float(e->button.pressure);
+     push_text("xtilt");   push_float(e->button.xtilt);
+     push_text("ytilt");   push_float(e->button.ytilt);
+     push_text("state");   push_int(e->button.state);
+     push_text("button");    push_int(e->button.button);
+     push_text("deviceid");push_int(e->button.deviceid);
+     push_text("x_root");  push_float(e->button.x_root);
+     push_text("y_root");  push_int(e->button.y_root);
+     break;
+     
+   case GDK_KEY_PRESS:
+     push_text("type");   push_text("key_press");
+     goto key_event;
+
+   case GDK_KEY_RELEASE:
+     push_text("type");   push_text("key_release");
+  key_event:
+     push_text("time");   push_int(e->key.time);
+     push_text("state");   push_int(e->key.state);
+     push_text("keyval");   push_int(e->key.keyval);
+     if(e->key.string)
+     {
+       push_text("data");     
+       push_string(make_shared_binary_string(e->key.string, e->key.length));
+     }
+     break;
+
+   case GDK_ENTER_NOTIFY:
+     push_text("type");   push_text("enter_notify");
+     goto enter_event;
+   case GDK_LEAVE_NOTIFY:
+     push_text("type");   push_text("leave_notify");
+  enter_event:
+     push_text("detail"); push_int(e->crossing.detail);
+     break;
+
+   case GDK_FOCUS_CHANGE:
+     push_text("type");   push_text("focus");
+     break;
+
+   case GDK_CONFIGURE:
+     push_text("type");   push_text("configure");
+     push_text("x"); push_int(e->configure.x);
+     push_text("y"); push_int(e->configure.x);
+     push_text("width"); push_int(e->configure.width);
+     push_text("height"); push_int(e->configure.height);
+     break;
+
+   case GDK_MAP:
+     push_text("type");   push_text("map");
+     break;
+   case GDK_UNMAP:
+     push_text("type");   push_text("unmap");
+     break;
+
+   case GDK_PROPERTY_NOTIFY:
+     push_text("type");   push_text("property");
+     break;
+
+   case GDK_SELECTION_CLEAR:
+     push_text("type");   push_text("selection_clear");
+     break;
+
+   case GDK_SELECTION_REQUEST:
+     push_text("type");   push_text("selection_request");
+     break;
+
+   case GDK_SELECTION_NOTIFY:
+     push_text("type");   push_text("selection_notify");
+     break;
+
+   case GDK_PROXIMITY_IN:
+     push_text("type");   push_text("proximity_in");
+     break;
+   case GDK_PROXIMITY_OUT:
+     push_text("type");   push_text("proximity_out");
+     break;
+
+   case GDK_CLIENT_EVENT:
+     push_text("type"); push_text("client");
+     break;
+
+   case GDK_VISIBILITY_NOTIFY:
+     push_text("type"); push_text("visibility");
+     break;
+
+   case GDK_NO_EXPOSE:
+     push_text("type"); push_text("noexpose");
+     break;
+  }
+  f_aggregate_mapping( sp - osp );
+}
+
+
+int pgtk_signal_func_wrapper(GtkObject *obj,struct signal_data *d,
+                             int nparams, GtkArg *params)
+{
+  int i, j=0, res, return_value = 0;
+  push_svalue(&d->args);
+  push_gtkobject( obj );
+  for(i=0; i<nparams; i++)
+  {
+    switch( params[i].type )
+    {
+     case GTK_TYPE_INT:
+     case GTK_TYPE_ENUM:
+     case GTK_TYPE_FLAGS:
+       push_int( (int)GTK_VALUE_INT(params[i]) );
+       break;
+     case GTK_TYPE_BOOL:
+       push_int( (int)GTK_VALUE_BOOL(params[i]) );
+       break;
+     case GTK_TYPE_UINT:
+       push_int( (int)GTK_VALUE_UINT(params[i]) );
+       break;
+     case GTK_TYPE_LONG:
+       push_int( (int)GTK_VALUE_LONG(params[i]) );
+       break;
+
+     case GTK_TYPE_CHAR:
+       push_int( (int)((unsigned char)GTK_VALUE_CHAR( params[i] )) );
+       break;
+
+     case GTK_TYPE_ULONG:
+       push_int( (int)GTK_VALUE_ULONG(params[i]) );
+       break;
+     case GTK_TYPE_INVALID:
+     case GTK_TYPE_NONE:
+       push_int( 0 );
+       break;
+     case GTK_TYPE_FLOAT:
+       push_float( (float)GTK_VALUE_FLOAT(params[i]) );
+       break;
+     case GTK_TYPE_DOUBLE:
+       push_float( (float)GTK_VALUE_DOUBLE(params[i]) );
+       break;
+
+     case GTK_TYPE_POINTER: /* These probably need fixing.. / Hubbe */
+     case GTK_TYPE_FOREIGN:
+
+     case GTK_TYPE_STRING:
+       if(GTK_VALUE_STRING( params[i] ))
+	 push_text( GTK_VALUE_STRING( params[i] ) );
+       else
+	 push_text( "" );
+       break;
+
+     case GTK_TYPE_OBJECT:
+       push_gtkobject( GTK_VALUE_OBJECT( params[i] ) );
+       break;
+
+     default:
+       {
+	 char *n = gtk_type_name( params[i].type );
+         if(n)
+         {
+           int ok = 0;
+           switch(n[3])
+           {
+            case 'A':
+              if(!strcmp(n, "GtkAccelFlags")) 
+              {
+                push_int( GTK_VALUE_UINT( params[i] ) );
+                ok=1;
+              }           
+              else if(!strcmp(n, "GtkAccelGroup")) 
+              {
+                ok=1;
+                gtk_accel_group_ref( (void *)GTK_VALUE_POINTER(params[i]) );
+                push_pgdkobject( GTK_VALUE_POINTER(params[i]), 
+                                 pgtk_accel_group_program); 
+              }
+              break;
+
+            case 'C':
+              if(!strcmp(n, "GtkCTreeNode"))
+              {
+                ok=1;
+                push_pgdkobject( GTK_VALUE_POINTER(params[i]), 
+                                 pgtk_CTreeNode_program);
+              } 
+              else if(!strcmp(n, "GtkCTreeRow"))
+              {
+                ok=1;
+                push_pgdkobject( GTK_VALUE_POINTER(params[i]), 
+                                 pgtk_CTreeRow_program);
+              }
+              break;
+
+            case 'D':
+              if(!strcmp(n, "GdkDragContext")) 
+              {
+                ok=1;
+                push_pgdkobject( GTK_VALUE_POINTER(params[i]), 
+                                 pgtk_GdkDragContext_program); 
+              }
+              break;
+
+            case 'E':
+              if(!strcmp(n, "GdkEvent"))
+              {
+                return_value = 1;
+                ok=1;
+                push_gdk_event( GTK_VALUE_POINTER( params[i] ) );
+              } 
+              break;
+
+            case 'M':
+              if(!strcmp(n, "GdkModifierType")) 
+              {
+                ok=1;
+                push_int( GTK_VALUE_UINT( params[i] ) );
+              }
+              break;
+
+            case 'S':
+              if(!strcmp(n, "GtkSelectionData")) 
+              {
+                ok=1;
+                push_pgdkobject( GTK_VALUE_POINTER(params[i]), 
+                                 pgtk_selection_data_program);
+              }
+              break;
+
+           }
+           if(!ok)
+           {
+             fprintf(stderr,"Unknown param type: %s<value=%p>\n",
+                     n, GTK_VALUE_POINTER(params[i]));
+             push_text( n );
+           }
+         }
+	 else
+	   push_int( 0 );
+       }
+    }
+    j++;
+  }
+  apply_svalue(&d->cb, 2+j);
+  res = sp[-1].u.integer;
+  pop_stack();
+  if( return_value )
+  { 
+    if( params[1].type == GTK_TYPE_POINTER)
+    {
+      gint *return_val;
+      return_val = GTK_RETLOC_BOOL( params[ 1 ] );
+      if(return_val)
+        *return_val = res;
+    }
+  }
+  return res;
+}
+
+void pgtk_free_signal_data( struct signal_data *s)
+{
+  free_svalue( &s->cb );
+  free_svalue( &s->args );
+  free(s);
+}