diff --git a/.gitattributes b/.gitattributes
index 0b298eb4ab5e422c01e34d4afac9fb197ec0ef27..2bce27d2944865be8b482400e322641ca24abbbe 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -89,6 +89,7 @@ testfont binary
 /src/modules/Image/lzw.h foreign_ident
 /src/modules/Image/matrix.c foreign_ident
 /src/modules/Image/mkdoc.pike foreign_ident
+/src/modules/Image/mkwmml.pike foreign_ident
 /src/modules/Image/operator.c foreign_ident
 /src/modules/Image/pattern.c foreign_ident
 /src/modules/Image/pnm.c foreign_ident
diff --git a/src/modules/Image/Makefile b/src/modules/Image/Makefile
index bae604d75f2ea6b39f4710f28b67aea4aa58e73d..36c8b1d270948045c1053010d90a186a48f970d8 100644
--- a/src/modules/Image/Makefile
+++ b/src/modules/Image/Makefile
@@ -6,14 +6,20 @@ DOCFILES = doc-header \
    encodings/gif_lzw.h encodings/pnm.c \
    doc-footer
 
+WMMLDOCPLACE = ../../../tutorial/Image.wmml
+
 pike=pike
 
 default:
 	echo "This makefile only builds documentation. Please run configure."
-	echo "To build documentation, type 'make doc'."
+	echo "To build HTML documentation, type 'make doc'."
+	echo "To build WMML documentation, type 'make wmml'."
 
-docs:	$(DOCFILES) mkdoc.pike Makefile
+doc:	$(DOCFILES) mkdoc.pike Makefile
 	$(pike) mkdoc.pike $(DOCFILES)
 
-doc:	docs
+$(WMMLDOCPLACE): $(DOCFILES) mkwmml.pike Makefile
+	$(pike) mkwmml.pike $(DOCFILES) >$(WMMLDOCPLACE)
+
+wmml:	$(WMMLDOCPLACE)
 
diff --git a/src/modules/Image/colortable.c b/src/modules/Image/colortable.c
index d95de9dc870cfb9235d2b2c0c41db03b86d0b48f..eaf6deaf4a261a960bbd2e78d5018415c37f7a91 100644
--- a/src/modules/Image/colortable.c
+++ b/src/modules/Image/colortable.c
@@ -1,11 +1,11 @@
 #include <config.h>
 
-/* $Id: colortable.c,v 1.24 1997/11/09 18:40:50 mirar Exp $ */
+/* $Id: colortable.c,v 1.25 1997/11/10 05:41:08 mirar Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: colortable.c,v 1.24 1997/11/09 18:40:50 mirar Exp $
+**!	$Id: colortable.c,v 1.25 1997/11/10 05:41:08 mirar Exp $
 **! class colortable
 **!
 **!	This object keeps colortable information,
@@ -21,7 +21,7 @@
 #undef COLORTABLE_REDUCE_DEBUG
 
 #include "global.h"
-RCSID("$Id: colortable.c,v 1.24 1997/11/09 18:40:50 mirar Exp $");
+RCSID("$Id: colortable.c,v 1.25 1997/11/10 05:41:08 mirar Exp $");
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -3040,7 +3040,7 @@ void image_colortable_map(INT32 args)
 **!	in the colorspace and comparing grey levels.
 **!
 **!	Default factors are 3, 4 and 1; blue is much 
-**!	darker than green. Compare with <ref>Image.image::grey</ref>().
+**!	darker than green. Compare with <ref>Image.image->grey</ref>().
 **!
 **! returns the called object
 **!
diff --git a/src/modules/Image/doc-footer b/src/modules/Image/doc-footer
index 4f7170fde5616d16abda51e8300b2f36ccc9d23b..245ad49d3bba9d64800783819daf88dc569d220b 100644
--- a/src/modules/Image/doc-footer
+++ b/src/modules/Image/doc-footer
@@ -1,3 +1,3 @@
 **! module Image
 **! note
-**!	</pre>
+**!	</pre></font>
diff --git a/src/modules/Image/doc-header b/src/modules/Image/doc-header
index 92600296b2678f18390c0ece718fa50155e50b9c..3c123cfa4571e155878d7e4e6333ca57c15529a3 100644
--- a/src/modules/Image/doc-header
+++ b/src/modules/Image/doc-header
@@ -22,4 +22,4 @@
 **!	</tr>
 **!	</table>
 **! note
-**!	<font size=-1><pre>file versions:
+**!	<font size=-1><pre>Image module documentation is based on these file versions:
diff --git a/src/modules/Image/doc/Image.colortable.html b/src/modules/Image/doc/Image.colortable.html
index 1d678cde01237fbc44413252661a85f224b83454..6618c9d98d593c890218559ac7c2a73cd0a321ac 100644
--- a/src/modules/Image/doc/Image.colortable.html
+++ b/src/modules/Image/doc/Image.colortable.html
@@ -39,35 +39,35 @@ Map colors in an image object to the colors in
 
 <p>     <table><tr valign=center>
      <td></td>
-     <td><a href=illustrations.html#illustration_0.gif><img border=0 src=illustration_0.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_1.gif><img border=0 src=illustration_1.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_2.gif><img border=0 src=illustration_2.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_3.gif><img border=0 src=illustration_3.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_4.gif><img border=0 src=illustration_4.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
      <td>no dither</td>
      </tr><tr valign=center>
      <td></td>
-     <td><a href=illustrations.html#illustration_5.gif><img border=0 src=illustration_5.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_6.gif><img border=0 src=illustration_6.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_7.gif><img border=0 src=illustration_7.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_8.gif><img border=0 src=illustration_8.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_9.gif><img border=0 src=illustration_9.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
      <td><tt><a href=Image.colortable.html#floyd_steinberg>floyd_steinberg</a></tt> dither</td>
      </tr><tr valign=center>
      <td></td>
-     <td><a href=illustrations.html#illustration_10.gif><img border=0 src=illustration_10.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_11.gif><img border=0 src=illustration_11.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_12.gif><img border=0 src=illustration_12.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_13.gif><img border=0 src=illustration_13.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_14.gif><img border=0 src=illustration_14.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
      <td><tt><a href=Image.colortable.html#ordered>ordered</a></tt> dither</td>
      </tr><tr valign=center>
-     <td><img src=lena.gif width=67 height=67></td>
-     <td><a href=illustrations.html#illustration_16.gif><img border=0 src=illustration_16.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_17.gif><img border=0 src=illustration_17.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_18.gif><img border=0 src=illustration_18.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_19.gif><img border=0 src=illustration_19.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_20.gif><img border=0 src=illustration_20.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
      <td><tt><a href=Image.colortable.html#randomcube>randomcube</a></tt> dither</td>
      </tr><tr valign=center>
      <td>original</td>
@@ -323,9 +323,9 @@ Set the colortable to use the cubicles algorithm to lookup
 <p>     In some cases, the <tt><a href=Image.colortable.html#full>full</a></tt> method is faster.
 
 <p>     <table><tr valign=center>
-     <td><img src=lena.gif width=67 height=67></td>
-     <td><a href=illustrations.html#illustration_3.gif><img border=0 src=illustration_3.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_23.gif><img border=0 src=illustration_23.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
      </tr><tr valign=center>
      <td>original</td>
      <td>default cubicles,<br>16 colors</td>
@@ -383,9 +383,9 @@ Set dithering method to floyd_steinberg.
      algorithm (for computer graphics wizards). 
 
 <p>     <table><tr valign=center>
-     <td><img src=lena.gif width=67 height=67></td>
-     <td><a href=illustrations.html#illustration_25.gif><img border=0 src=illustration_25.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_26.gif><img border=0 src=illustration_26.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
      </tr><tr valign=center>
      <td>original</td>
      <td>floyd_steinberg to a 4×4×4 colorcube</td>
@@ -493,10 +493,10 @@ Set ordered dithering, which gives a position-dependent error added
      to the pixel values. 
 
 <p>     <table><tr valign=center>
-     <td><img src=lena.gif width=67 height=67></td>
-     <td><a href=illustrations.html#illustration_28.gif><img border=0 src=illustration_28.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_29.gif><img border=0 src=illustration_29.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_30.gif><img border=0 src=illustration_30.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
      </tr><tr valign=top>
      <td>original</td>
      <td colspan=2>mapped to <br><tt>Image.colortable(6,6,6)-></tt></td>
@@ -506,10 +506,10 @@ Set ordered dithering, which gives a position-dependent error added
      <td><tt>ordered()</tt></td>
      <td><tt>ordered<br> (42,42,42, 8,8,<br> 0,0, 0,1, 1,0)</tt></td>
      </tr><tr valign=top>
-     <td><a href=illustrations.html#illustration_31.gif><img border=0 src=illustration_31.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_32.gif><img border=0 src=illustration_32.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_33.gif><img border=0 src=illustration_33.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_34.gif><img border=0 src=illustration_34.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
+     <td></td>
      </tr></table>
 </blockquote>
 <h4>ARGUMENTS</h4>
@@ -572,9 +572,9 @@ Set random cube dithering.
      and blue and the randomcube method has three random errors.
 
 <p>     <table><tr valign=center>
-     <td><img src=lena.gif width=67 height=67></td>
-     <td><a href=illustrations.html#illustration_36.gif><img border=0 src=illustration_36.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_37.gif><img border=0 src=illustration_37.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
      </tr><tr valign=top>
      <td>original</td>
      <td colspan=2>mapped to <br><tt>Image.colortable(4,4,4)-></tt></td>
@@ -583,9 +583,9 @@ Set random cube dithering.
      <td>randomcube()</td>
      <td>randomgrey()</td>
      </tr><tr valign=top>
-     <td><a href=illustrations.html#illustration_31.gif><img border=0 src=illustration_31.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_39.gif><img border=0 src=illustration_39.gif width=67 height=67></a></td>
-     <td><a href=illustrations.html#illustration_40.gif><img border=0 src=illustration_40.gif width=67 height=67></a></td>
+     <td></td>
+     <td></td>
+     <td></td>
      </tr></table>
 </blockquote>
 <h4>ARGUMENTS</h4>
diff --git a/src/modules/Image/doc/Image.html b/src/modules/Image/doc/Image.html
index f8825ddb5aceb417de3f169b881589b7a0cdf28f..751eda8b733057edc551c3b2ca2f52f873063a5b 100644
--- a/src/modules/Image/doc/Image.html
+++ b/src/modules/Image/doc/Image.html
@@ -29,24 +29,24 @@ This module adds image-drawing and -manipulating
 
 <h4>NOTE</h4>
 <blockquote>
-<font size=-1><pre>file versions:
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     $Id: Image.html,v 1.14 1997/11/07 16:37:52 mirar Exp $
-     </pre>
+<font size=-1><pre>Image module documentation is based on these file versions:
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     $Id: Image.html,v 1.15 1997/11/10 05:41:16 mirar Exp $
+     </pre></font>
 </blockquote>
diff --git a/src/modules/Image/doc/illustrations.html b/src/modules/Image/doc/illustrations.html
index 61af182988b736d4e043d4627aa577764bed75af..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391 100644
--- a/src/modules/Image/doc/illustrations.html
+++ b/src/modules/Image/doc/illustrations.html
@@ -1,87 +0,0 @@
-<a name=illustration_0.gif><img border=0 src=illustration_0.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),2); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_1.gif><img border=0 src=illustration_1.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),4); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_2.gif><img border=0 src=illustration_2.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),8); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_3.gif><img border=0 src=illustration_3.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),16); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_4.gif><img border=0 src=illustration_4.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),32); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_5.gif><img border=0 src=illustration_5.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),2)->floyd_steinberg(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_6.gif><img border=0 src=illustration_6.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),4)->floyd_steinberg(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_7.gif><img border=0 src=illustration_7.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),8)->floyd_steinberg(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_8.gif><img border=0 src=illustration_8.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),16)->floyd_steinberg(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_9.gif><img border=0 src=illustration_9.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),32)->floyd_steinberg(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_10.gif><img border=0 src=illustration_10.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),2)->ordered(60,60,60); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_11.gif><img border=0 src=illustration_11.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),4)->ordered(45,45,45); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_12.gif><img border=0 src=illustration_12.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),8)->ordered(40,40,40); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_13.gif><img border=0 src=illustration_13.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),16)->ordered(40,40,40); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_14.gif><img border=0 src=illustration_14.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),32)->ordered(15,15,15); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_16.gif><img border=0 src=illustration_16.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),2)->randomcube(60,60,60); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_17.gif><img border=0 src=illustration_17.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),4)->randomcube(45,45,45); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_18.gif><img border=0 src=illustration_18.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),8)->randomcube(40,40,40); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_19.gif><img border=0 src=illustration_19.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),16)->randomcube(40,40,40); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_20.gif><img border=0 src=illustration_20.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),32)->randomcube(15,15,15); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_23.gif><img border=0 src=illustration_23.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),16)->cubicles(4,5,4,200); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_25.gif><img border=0 src=illustration_25.gif width=67 height=67 align=right><pre> object c=Image.colortable(4,4,4)->floyd_steinberg(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_26.gif><img border=0 src=illustration_26.gif width=67 height=67 align=right><pre> object c=Image.colortable(lena(),16)->floyd_steinberg(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_28.gif><img border=0 src=illustration_28.gif width=67 height=67 align=right><pre> object c=Image.colortable(6,6,6)->ordered(42,42,42,2,2); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_29.gif><img border=0 src=illustration_29.gif width=67 height=67 align=right><pre> object c=Image.colortable(6,6,6)->ordered(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_30.gif><img border=0 src=illustration_30.gif width=67 height=67 align=right><pre> object c=Image.colortable(6,6,6)->ordered(42,42,42,8,8,0,0,0,1,1,0); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_31.gif><img border=0 src=illustration_31.gif width=67 height=67 align=right><pre> 
-             object i=Image.image(lena()->xsize(),lena()->ysize()); 
-             i->tuned_box(0,0,i->xsize()-1,i->ysize()-1,
-                  ({({0,0,0}),({0,0,0}),({255,255,255}),({255,255,255})})); 
-             return i; 
-     </pre></a><br clear=all><hr><a name=illustration_32.gif><img border=0 src=illustration_32.gif width=67 height=67 align=right><pre> 
-             object i=Image.image(lena()->xsize(),lena()->ysize()); 
-             i->tuned_box(0,0,i->xsize()-1,i->ysize()-1,
-                  ({({0,0,0}),({0,0,0}),({255,255,255}),({255,255,255})})); 
-             object c=Image.colortable(6,6,6)->ordered(42,42,42,2,2); 
-             return c*i; 
-     </pre></a><br clear=all><hr><a name=illustration_33.gif><img border=0 src=illustration_33.gif width=67 height=67 align=right><pre> 
-             object i=Image.image(lena()->xsize(),lena()->ysize()); 
-             i->tuned_box(0,0,i->xsize()-1,i->ysize()-1,
-                  ({({0,0,0}),({0,0,0}),({255,255,255}),({255,255,255})})); 
-             object c=Image.colortable(6,6,6)->ordered(); 
-             return c*i; 
-     </pre></a><br clear=all><hr><a name=illustration_34.gif><img border=0 src=illustration_34.gif width=67 height=67 align=right><pre> 
-             object i=Image.image(lena()->xsize(),lena()->ysize()); 
-             i->tuned_box(0,0,i->xsize()-1,i->ysize()-1,
-                  ({({0,0,0}),({0,0,0}),({255,255,255}),({255,255,255})})); 
-             object c=Image.colortable(6,6,6)->ordered(42,42,42,8,8,0,0,0,1,1,0); 
-             return c*i; 
-     </pre></a><br clear=all><hr><a name=illustration_36.gif><img border=0 src=illustration_36.gif width=67 height=67 align=right><pre> object c=Image.colortable(4,4,4)->randomcube(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_37.gif><img border=0 src=illustration_37.gif width=67 height=67 align=right><pre> object c=Image.colortable(4,4,4)->randomgrey(); return c*lena(); </pre></a><br clear=all><hr><a name=illustration_39.gif><img border=0 src=illustration_39.gif width=67 height=67 align=right><pre> 
-             object i=Image.image(lena()->xsize(),lena()->ysize()); 
-             i->tuned_box(0,0,i->xsize()-1,i->ysize()-1,
-                  ({({0,0,0}),({0,0,0}),({255,255,255}),({255,255,255})})); 
-             object c=Image.colortable(4,4,4)->randomcube(); 
-             return c*i; 
-     </pre></a><br clear=all><hr><a name=illustration_40.gif><img border=0 src=illustration_40.gif width=67 height=67 align=right><pre> 
-             object i=Image.image(lena()->xsize(),lena()->ysize()); 
-             i->tuned_box(0,0,i->xsize()-1,i->ysize()-1,
-                  ({({0,0,0}),({0,0,0}),({255,255,255}),({255,255,255})})); 
-             object c=Image.colortable(4,4,4)->randomgrey(); 
-             return c*i; 
-     </pre></a><br clear=all><hr><a name=illustration_41.gif><img border=0 src=illustration_41.gif width=67 height=67 align=right><pre>
-     return lena()->apply_matrix(
-     ({({1,2,1}),
-       ({2,5,2}),
-       ({1,2,1})})
-     );
-     </pre></a><br clear=all><hr><a name=illustration_43.gif><img border=0 src=illustration_43.gif width=67 height=67 align=right><pre>
-     return lena()->apply_matrix(
-     ({({-1,-1,-1}),
-       ({-1,14,-1}),
-       ({-1,-1,-1})})
-     );
-     </pre></a><br clear=all><hr><a name=illustration_44.gif><img border=0 src=illustration_44.gif width=67 height=67 align=right><pre>
-     return lena()->apply_matrix(
-     ({({1, 1,1}),
-       ({1,-8,1}),
-       ({1, 1,1})})
-     );
-     </pre></a><br clear=all><hr><a name=illustration_45.gif><img border=0 src=illustration_45.gif width=67 height=67 align=right><pre>
-     return lena()->apply_matrix(
-     ({({0, 0,0}),
-       ({1,-2,1}),
-       ({0, 0,0})})
-     );
-     </pre></a><br clear=all><hr><a name=illustration_46.gif><img border=0 src=illustration_46.gif width=67 height=67 align=right><pre>
-     return lena()->apply_matrix(
-     ({({2, 1, 0}),
-       ({1, 0,-1}),
-       ({0,-1,-2})}), 128,128,128, 3
-     );
-     </pre></a><br clear=all><hr><a name=illustration_47.gif><img border=0 src=illustration_47.gif width=67 height=67 align=right><pre>
-     return lena()->grey()->apply_matrix(
-     ({({2, 1, 0}),
-       ({1, 0,-1}),
-       ({0,-1,-2})}), 128,128,128, 3
-     );
-     </pre></a><br clear=all><hr><a name=illustration_49.gif><img border=0 src=illustration_49.gif width=67 height=67 align=right><pre> return lena()->color(128,128,255); </pre></a><br clear=all><hr><a name=illustration_51.gif><img border=0 src=illustration_51.gif width=67 height=67 align=right><pre> return lena()->distancesq(255,0,128); </pre></a><br clear=all><hr><a name=illustration_53.gif><img border=0 src=illustration_53.gif width=67 height=67 align=right><pre> return lena()->grey(); </pre></a><br clear=all><hr><a name=illustration_54.gif><img border=0 src=illustration_54.gif width=67 height=67 align=right><pre> return lena()->grey(0,0,255); </pre></a><br clear=all><hr><a name=illustration_56.gif><img border=0 src=illustration_56.gif width=67 height=67 align=right><pre> return lena()->hsv_to_rgb(); </pre></a><br clear=all><hr><a name=illustration_57.gif><img border=0 src=illustration_57.gif width=67 height=67 align=right><pre> return lena()->rgb_to_hsv(); </pre></a><br clear=all><hr><a name=illustration_58.gif><img border=0 src=illustration_58.gif width=67 height=67 align=right><pre>
-     return image(67,67)->tuned_box(0,0, 67,67,
-                      ({ ({ 255,255,128 }), ({ 0,255,128 }),
-                         ({ 255,255,255 }), ({ 0,255,255 })}));
-     </pre></a><br clear=all><hr><a name=illustration_59.gif><img border=0 src=illustration_59.gif width=67 height=67 align=right><pre>
-     return image(67,67)->tuned_box(0,0, 67,67,
-                      ({ ({ 255,255,128 }), ({ 0,255,128 }),
-                         ({ 255,255,255 }), ({ 0,255,255 })}))
-          ->hsv_to_rgb();
-     </pre></a><br clear=all><hr><a name=illustration_60.gif><img border=0 src=illustration_60.gif width=67 height=67 align=right><pre>
-     return image(67,67)->tuned_box(0,0, 67,67,
-                      ({ ({ 255,255,128 }), ({ 0,255,128 }),
-                         ({ 255,255,255 }), ({ 0,255,255 })}))
-          ->rgb_to_hsv();
-     </pre></a><br clear=all><hr><a name=illustration_62.gif><img border=0 src=illustration_62.gif width=67 height=67 align=right><pre> return lena()->invert(); </pre></a><br clear=all><hr><a name=illustration_63.gif><img border=0 src=illustration_63.gif width=67 height=67 align=right><pre> return lena()->rgb_to_hsv()->invert()->hsv_to_rgb(); </pre></a><br clear=all><hr><a name=illustration_65.gif><img border=0 src=illustration_65.gif width=67 height=67 align=right><pre> return lena()->mirrorx(); </pre></a><br clear=all><hr><a name=illustration_67.gif><img border=0 src=illustration_67.gif width=67 height=67 align=right><pre> return lena()->mirrory(); </pre></a><br clear=all><hr><a name=illustration_69.gif><img border=0 src=illustration_69.gif width=67 height=67 align=right><pre> return lena()->grey()->modify_by_intensity(1,0,0,0,({255,0,0}),({0,255,0})); </pre></a><br clear=all><hr><a name=illustration_70.gif><img border=0 src=illustration_70.gif width=200 height=100 align=right><pre>return image(200,100)->noise( ({0,({255,0,0}), 0.3,({0,255,0}), 0.6,({0,0,255}), 0.8,({255,255,0})}), 0.005,0,0,0.2 );</pre></a><br clear=all><hr><a name=illustration_72.gif><img border=0 src=illustration_72.gif width=87 height=88 align=right><pre> return lena()->rotate(15,255,0,0); </pre></a><br clear=all><hr><a name=illustration_73.gif><img border=0 src=illustration_73.gif width=87 height=88 align=right><pre> return lena()->rotate_expand(15); </pre></a><br clear=all><hr><a name=illustration_75.gif><img border=0 src=illustration_75.gif width=67 height=67 align=right><pre> return lena()->rotate_ccw(); </pre></a><br clear=all><hr><a name=illustration_77.gif><img border=0 src=illustration_77.gif width=67 height=67 align=right><pre> return lena()->rotate_cw(); </pre></a><br clear=all><hr><a name=illustration_79.gif><img border=0 src=illustration_79.gif width=82 height=67 align=right><pre> return lena()->skewx(15,255,0,0); </pre></a><br clear=all><hr><a name=illustration_80.gif><img border=0 src=illustration_80.gif width=82 height=67 align=right><pre> return lena()->skewx_expand(15); </pre></a><br clear=all><hr><a name=illustration_82.gif><img border=0 src=illustration_82.gif width=67 height=82 align=right><pre> return lena()->skewy(15,255,0,0); </pre></a><br clear=all><hr><a name=illustration_83.gif><img border=0 src=illustration_83.gif width=67 height=82 align=right><pre> return lena()->skewy_expand(15); </pre></a><br clear=all><hr><a name=illustration_85.gif><img border=0 src=illustration_85.gif width=67 height=67 align=right><pre> return lena()->threshold(90,100,110); </pre></a><br clear=all><hr><a name=illustration_87.gif><img border=0 src=illustration_87.gif width=67 height=67 align=right><pre> return lena()->copy()->tuned_box(0,0,lena()->xsize(),lena()->ysize(),({({255,0,0}),({0,255,0}),({0,0,255}),({255,255,0})})); </pre></a><br clear=all><hr><a name=illustration_88.gif><img border=0 src=illustration_88.gif width=67 height=67 align=right><pre> return lena()->copy()->tuned_box(0,0,lena()->xsize(),lena()->ysize(),({({255,0,0,255}),({0,255,0,128}),({0,0,255,128}),({255,255,0})})); </pre></a><br clear=all><hr><a name=illustration_89.gif><img border=0 src=illustration_89.gif width=200 height=100 align=right><pre>return image(200,100)->
-     turbulence( ({0,({229,204,204}), 0.9,({229,20,20}), 0.9,0}));</pre></a><br clear=all><hr>
\ No newline at end of file
diff --git a/src/modules/Image/encodings/gif.c b/src/modules/Image/encodings/gif.c
index 686f3671d0acbbc421bd66d7494f62724109fee9..7b529975ba1269a68ab14f8d54aba845e1b0ff84 100644
--- a/src/modules/Image/encodings/gif.c
+++ b/src/modules/Image/encodings/gif.c
@@ -1,9 +1,9 @@
-/* $Id: gif.c,v 1.15 1997/11/09 18:40:54 mirar Exp $ */
+/* $Id: gif.c,v 1.16 1997/11/10 05:41:19 mirar Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: gif.c,v 1.15 1997/11/09 18:40:54 mirar Exp $
+**!	$Id: gif.c,v 1.16 1997/11/10 05:41:19 mirar Exp $
 **! submodule GIF
 **!
 **!	This submodule keep the GIF encode/decode capabilities
@@ -31,7 +31,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: gif.c,v 1.15 1997/11/09 18:40:54 mirar Exp $");
+RCSID("$Id: gif.c,v 1.16 1997/11/10 05:41:19 mirar Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -378,7 +378,7 @@ static void image_gif__gce_block(INT32 args)
 **! arg string colortable
 **!	Colortable with colors to write as palette.
 **!	If this argument is zero, no local colortable is written.
-**!	Colortable string len must be 1<<bpp.
+**!	Colortable string len must be 1&lt;&lt;bpp.
 **! arg int interlace
 **!     Interlace index data and set interlace bit. The given string
 **!	should _not_ be pre-interlaced.
diff --git a/src/modules/Image/image.c b/src/modules/Image/image.c
index f4e5398b89ae9f6cd7ccd8341fdd97e823e995b1..65f8a7996e3f00ca1b02757ac09bfdff50b1ee2e 100644
--- a/src/modules/Image/image.c
+++ b/src/modules/Image/image.c
@@ -1,9 +1,9 @@
-/* $Id: image.c,v 1.56 1997/11/09 18:54:48 mirar Exp $ */
+/* $Id: image.c,v 1.57 1997/11/10 05:41:12 mirar Exp $ */
 
 /*
 **! module Image
 **! note
-**!	$Id: image.c,v 1.56 1997/11/09 18:54:48 mirar Exp $
+**!	$Id: image.c,v 1.57 1997/11/10 05:41:12 mirar Exp $
 **! class image
 **!
 **!	The main object of the <ref>Image</ref> module, this object
@@ -84,7 +84,7 @@
 
 #include "stralloc.h"
 #include "global.h"
-RCSID("$Id: image.c,v 1.56 1997/11/09 18:54:48 mirar Exp $");
+RCSID("$Id: image.c,v 1.57 1997/11/10 05:41:12 mirar Exp $");
 #include "pike_macros.h"
 #include "object.h"
 #include "constants.h"
@@ -2159,7 +2159,7 @@ void image_select_from(INT32 args)
 **!	);
 **!	</illustration>
 **!	</td>
-**!	<tr><td></td><td>greyed</td></table>
+**!	<tr><td></td><td>greyed</td></tr></table>
 **!
 **!	This function is not very fast -- and it's hard to 
 **!	optimize it more, not using assembler.
diff --git a/src/modules/Image/mkwmml.pike b/src/modules/Image/mkwmml.pike
new file mode 100644
index 0000000000000000000000000000000000000000..5d008b017c216a59cce981e838e3f792a7380822
--- /dev/null
+++ b/src/modules/Image/mkwmml.pike
@@ -0,0 +1,518 @@
+/* $Id: mkwmml.pike,v 1.1 1997/11/10 05:41:13 mirar Exp $ */
+
+import Stdio;
+import Array;
+
+mapping parse=([]);
+int illustration_counter;
+
+#define error(X) throw( ({ (X), backtrace()[0..sizeof(backtrace())-2] }) )
+
+/*
+
+module : mapping <- moduleM
+	"desc" : text
+	"see also" : array of references 
+	"note" : mapping of "desc": text
+	"modules" : same as classes (below)
+	"classes" : mapping 
+		class : mapping <- classM
+	        	"see also" : array of references 
+			"desc" : text
+			"note" : mapping of "desc": text
+			"methods" : array of mappings <- methodM
+				"decl" : array of textlines of declarations
+				"desc" : text
+				"returns" : textline
+				"see also" : array of references 
+				"note" : mapping of "desc": text
+				"known bugs" : mapping of "desc": text
+				"args" : array of mappings <- argM
+					"args" : array of args names and types
+					"desc" : description
+				"names" : multiset of method name(s)
+		
+*/
+
+mapping moduleM, classM, methodM, argM, nowM, descM;
+
+mapping focM(mapping dest,string name,int line)
+{
+   return dest[name] || (dest[name]=(["_line":line]));
+}
+
+string stripws(string s)
+{
+   sscanf(s,"%*[ \t\n\r]%s",s);
+   s=reverse(s);
+   sscanf(s,"%*[ \t\n\r]%s",s);
+   return reverse(s);
+}
+
+mapping lower_nowM()
+{
+   if (nowM && 
+       (nowM==parse
+	|| nowM==classM
+	|| nowM==methodM
+	|| nowM==moduleM)) return nowM;
+   else return nowM=methodM;
+}
+
+void report(string s)
+{
+   stderr->write(s+"\n");
+}
+
+#define complain(X) (X)
+
+mapping keywords=
+(["module":lambda(string arg,int line) 
+	  { classM=descM=nowM=moduleM=focM(parse,stripws(arg),line); 
+	    methodM=0; 
+	    if (!nowM->classes) nowM->classes=([]); 
+	    if (!nowM->modules) nowM->modules=([]); 
+	    report("module "+arg); },
+  "class":lambda(string arg,int line) 
+	  { if (!moduleM) return complain("class w/o module");
+	    descM=nowM=classM=focM(moduleM->classes,stripws(arg),line); 
+	    methodM=0; report("class "+arg); },
+  "submodule":lambda(string arg,int line) 
+	  { if (!moduleM) return complain("submodule w/o module");
+	    classM=descM=nowM=moduleM=focM(moduleM->modules,stripws(arg),line);
+	    methodM=0;
+	    if (!nowM->classes) nowM->classes=([]); 
+	    if (!nowM->modules) nowM->modules=([]); 
+	    report("submodule "+arg); },
+  "method":lambda(string arg,int line)
+	  { if (!classM) return complain("method w/o class");
+	    if (!nowM || methodM!=nowM || methodM->desc || methodM->args || descM==methodM) 
+	    { if (!classM->methods) classM->methods=({});
+	      classM->methods+=({methodM=nowM=(["decl":({}),"_line":line])}); }
+	    methodM->decl+=({stripws(arg)}); descM=0; },
+  "arg":lambda(string arg,int line)
+	  {
+	     if (!methodM) return complain("arg w/o method");
+	     if (!methodM->args) methodM->args=({});
+	       methodM->args+=({argM=nowM=(["args":({}),"_line":line])}); 
+	     argM->args+=({arg}); descM=argM;
+	  },
+  "note":lambda(string arg,int line)
+	  {
+	     if (!lower_nowM()) 
+	        return complain("note w/o method, class or module");
+	     descM=nowM->note||(nowM->note=(["_line":line]));
+	  },
+  "bugs":lambda(string arg,int line)
+	  {
+	     if (!lower_nowM()) 
+	        return complain("bugs w/o method, class or module");
+	     descM=nowM->bugs||(nowM->bugs=(["_line":line]));
+	  },
+  "see":lambda(string arg,int line)
+	  {
+	     if (arg[0..4]!="also:")
+	        return complain("see w/o 'also:'\n");
+	     if (!lower_nowM()) 
+	        return complain("see also w/o method, class or module");
+	     nowM["see also"]=map(arg[5..]/",",stripws);
+	  },
+  "returns":lambda(string arg)
+	  {
+	     if (!methodM) 
+	        return complain("returns w/o method");
+	     methodM->returns=stripws(arg);
+	     descM=0; nowM=0;
+	  }
+]);
+
+string getridoftabs(string s)
+{
+   string res="";
+   for (;;)
+   {
+      int i;
+      if ((i=search(s,"\t"))==-1) return res+s;
+      res+=s[0..i-1]; 
+      s=s[i+1..];
+      res+="         "[(strlen(res)%8)..7];
+   }
+}
+
+
+object(File) make_file(string filename)
+{
+   stderr->write("creating "+filename+"...\n");
+   if (file_size(filename)>0)
+   {
+      rm(filename+"~");
+      mv(filename,filename+"~");
+   }
+   object f=File();
+   if (!f->open(filename,"wtc"))
+   {
+      stderr->write("failed.");
+      exit(1);
+   }
+   return f;
+}
+
+string synopsis_to_html(string s)
+{
+   string type,name,arg;
+   if (sscanf(s,"%s%*[ \t]%s(%s",type,name,arg)!=4)
+      sscanf(s,"%s(%s",name,arg),type="";
+
+   return 
+      type+" <b>"+name+"</b>("+
+      replace(arg,({","," "}),({", ","\240"}));
+}
+
+string htmlify(string s) 
+{
+#define HTMLIFY(S) \
+   (replace((S),({"->","&","\240"}),({"-&gt;","&amp;","&nbsp;"})))
+
+   string t="",u,v;
+   while (sscanf(s,"%s<%s>%s",u,v,s)==3)
+      t+=HTMLIFY(u)+"<"+v+">";
+   return t+HTMLIFY(s);
+}
+
+#define linkify(S) (replace((S),({"->","()"}),({".",""})))
+
+string make_nice_reference(string what,string prefix)
+{
+   string q;
+   if (search(what,".")==-1 &&
+       search(what,"->")==-1 &&
+       !parse[what])
+      q=prefix+what;
+   else 
+      q=what;
+
+   return "<link to="+linkify(q)+">"+what+"</link>";
+}
+
+string fixdesc(string s,string prefix,string where)
+{
+   s=stripws(s);
+
+   string t,u,v;
+
+   t=s; s="";
+   while (sscanf(t,"%s<ref>%s</ref>%s",t,u,v)==3)
+   {
+      s+=t+make_nice_reference(u,prefix);
+      t=v;
+   }
+   s+=t;
+
+   t=s; s="";
+   while (sscanf(t,"%s<illustration>%s</illustration>%s",t,u,v)==3)
+   {
+      s+=htmlify(replace(t,"\n\n","\n\n<p>"));
+
+      s+="<illustration __from__='"+where+"' src=lena.gif>\n"
+	 +replace(u,"lena()","src")+"</illustration>";
+
+      t=v;
+   }
+   s+=htmlify(replace(t,"\n\n","\n\n<p>"));
+
+   return s;
+}
+
+
+multiset(string) get_method_names(string *decls)
+{
+   string decl,name;
+   multiset(string) names=(<>);
+   foreach (decls,decl)
+   {
+      sscanf(decl,"%*s%*[\t ]%s%*[\t (]%*s",name);
+      names[name]=1;
+   }
+   return names;
+}
+
+
+string addprefix(string suffix,string prefix)
+{
+   return prefix+suffix;
+}
+
+void document(mapping huh,string name,string prefix,object f)
+{
+   string *names;
+
+   if (huh->names)
+      names=map(indices(huh->names),addprefix,name);
+   else
+      names=({name});
+
+   werror(name+" : "+names*","+"\n");
+
+// ANCHOR
+
+   f->write("<hr newpage>\n");
+   
+   foreach (names,string n)
+      f->write("<anchor name="+linkify(n)+">\n");
+
+   f->write("<dl>\n");
+
+// NAME
+
+   f->write("<dt><encaps>NAME</encaps><dd>\n");
+
+   foreach (names,n)
+      f->write("\t<tt>"+n+"</tt><br>\n");
+
+   f->write("<p>\n");
+
+// [SYNTAX]
+
+   if (huh->decl)
+   {
+      f->write("<dt><encaps>SYNTAX</encaps><dd>\n");
+
+      f->write(replace(htmlify(map(huh->decl,synopsis_to_html)*
+			       "<br>\n"),"\n","\n\t")+"\n");
+
+      f->write("<p>\n\n");
+   }
+
+// [DESCRIPTION]
+
+   if (huh->desc)
+   {
+      f->write("<dt><encaps>DESCRIPTION</encaps><dd>\n");
+      f->write(fixdesc(huh->desc,prefix,huh->_line)+"\n");
+      f->write("<p>\n\n");
+   }
+
+// [ARGUMENTS]
+
+   if (huh->args)
+   {
+      string rarg="";
+      f->write("<dt><encaps>ARGUMENTS</encaps><dd>\n");
+      
+      f->write("\t<table border=1 cellspacing=0><tr>\n"
+	       "\t<td align=left><font size=-2>argument(s)</font></td>"
+	       "\t<td align=left><font size=-2>description</font></td>"
+	       "</tr>\n\n");
+
+      foreach (huh->args,mapping arg)
+      {
+	 if (arg->desc)
+	 {
+	    f->write("\t<tr align=left><td valign=top>\n"
+		     +rarg+"\t\t<tt>"
+ 		     +arg->args*"</tt><br>\n\t\t<tt>"
+		     +"</tt></td>\n"
+		     +"\t<td valign=bottom>"
+		     +fixdesc(arg->desc,prefix,arg->_line)
+		     +"</td></tr>\n\n");
+	    rarg="";
+	 }
+	 else
+	 {
+	    rarg+="\t\t<tt>"
+	       +arg->args*"</tt><br>\n\t\t<tt>"+
+	       "</tt><br>\n";
+	 }
+      }
+      if (rarg!="") error("trailing args w/o desc on "+arg->_line+"\n");
+
+      f->write("</table><p>\n\n");
+   }
+
+// [RETURN VALUE]
+
+   if (huh->returns)
+   {
+      f->write("<dt><encaps>RETURN VALUE</encaps><dd>\n");
+      f->write(fixdesc(huh->returns,prefix,huh->_line)+"\n");
+      f->write("<p>\n\n");
+   }
+
+
+// [NOTE]
+
+   if (huh->note && huh->note->desc)
+   {
+      f->write("<dt><encaps>NOTA BENE</encaps><dd>\n");
+      f->write(fixdesc(huh->note->desc,prefix,huh->_line)+"\n");
+      f->write("<p>\n\n");
+   }
+
+// [SEE ALSO]
+
+   if (huh["see also"])
+   {
+      f->write("<dt><encaps>SEE ALSO</encaps><dd>\n");
+      f->write(map(huh["see also"],
+		    make_nice_reference,prefix)*",\n     "+"\n");
+      f->write("<p>\n\n");
+   }
+
+   f->write("</dl>\n\n");
+
+// ---childs----
+
+   if (huh->methods)
+   {
+      // postprocess methods to get names
+
+      multiset(string) method_names=(<>);
+      string *method_names_arr,method_name;
+      mapping method;
+
+      if (huh->methods) 
+	 foreach (huh->methods,method)
+	    method_names|=(method->names=get_method_names(method->decl));
+
+      method_names_arr=sort(indices(method_names));
+
+      // alphabetically
+
+      foreach (method_names_arr,method_name)
+	 if (method_names[method_name])
+	 {
+	    // find it
+	    foreach (huh->methods,method)
+	       if ( method->names[method_name] )
+	       {
+		  document(method,prefix,prefix,f);
+		  method_names-=method->names;
+	       }
+	    if (method_names[method_name])
+	       stderr->write("failed to find "+method_name+" again, wierd...\n");
+	 }
+
+      foreach(huh->methods,mapping child)
+      {
+	 document(child,prefix,prefix,f);
+      }
+   }
+
+   if (huh->classes)
+   {
+      foreach(indices(huh->classes),string n)
+      {
+	 f->write("\n\n\n<section title=\""+prefix+n+"\">\n");
+	 document(huh->classes[n],
+		  prefix+n,prefix+n+"->",f);
+	 f->write("</section title=\""+prefix+n+"\">\n");
+      }
+   }
+
+   if (huh->modules)
+   {
+      foreach(indices(huh->modules),string n)
+      {
+	 f->write("\n\n\n<section title=\""+prefix+n+"\">\n");
+	 document(huh->modules[n],
+		  prefix+n,prefix+n+".",f);
+	 f->write("</section title=\""+prefix+n+"\">\n");
+      }
+   }
+// end ANCHOR
+
+   foreach (names,string n)
+      f->write("</anchor name="+linkify(n)+">\n");
+   f->write("\n\n\n");
+}
+
+void make_doc_files()
+{
+   stderr->write("modules: "+sort(indices(parse))*", "+"\n");
+   
+   foreach (sort(indices(parse)),string module)
+      document(parse[module],module,module+".",stdout);
+}
+
+int main(int ac,string *files)
+{
+   string s,t;
+   int line;
+   string *ss=({""});
+   object f;
+
+   string currentfile;
+
+   nowM=parse;
+
+   stderr->write("reading and parsing data...\n");
+
+   files=files[1..];
+
+   for (;;)
+   {
+      int i;
+
+      if (!f) 
+      {
+	 if (!sizeof(files)) break;
+	 stderr->write("reading "+files[0]+"...\n");
+	 f=File();
+	 currentfile=files[0];
+	 files=files[1..];
+	 if (!f->open(currentfile,"r")) { f=0; continue; }
+	 t=0;
+	 ss=({""});
+	 line=0;
+      }
+
+      if (sizeof(ss)<2)
+      {
+	 if (t=="") { f=0; continue; }
+	 t=f->read(8192);
+	 s=ss[0];
+	 ss=t/"\n";
+	 ss[0]=s+ss[0];
+      }
+      s=ss[0]; ss=ss[1..];
+
+      line++;
+      if ((i=search(s,"**!"))!=-1)
+      {
+	 string kw,arg;
+
+	 sscanf(s[i+3..],"%*[ \t]%s%*[ \t]%s",kw,arg);
+	 if (keywords[kw])
+	 {
+	    string err;
+	    if ( (err=keywords[kw](arg,currentfile+" line "+line)) )
+	    {
+	       stderr->write(currentfile+" line "+line+": "+err+"\n");
+	       return 1;
+	    }
+	 }
+	 else 
+	 {
+//	    if (search(s,"$Id")!=-1) report("Id: "+s);
+	    if (!descM) descM=methodM;
+	    if (!descM)
+	    {
+	       stderr->write("Error on line "+line+": illegal description position\n");
+	       return 1;
+	    }
+	    if (!descM->desc) descM->desc="";
+	    else descM->desc+="\n";
+	    s=getridoftabs(s);
+	    descM->desc+=s[search(s,"**!")+3..];
+	 }
+      }
+   }
+
+//   stderr->write(sprintf("%O",parse));
+
+   stderr->write("making docs...\n\n");
+
+   make_doc_files();
+
+   return 0;
+}