diff --git a/tutorial/Wmml.pmod b/tutorial/Wmml.pmod
index 63f5686255c8ce08e9ef7f70b6984531ca50b079..2c006c68440986d22ae4ee9a3f7c77fae4bcda40 100644
--- a/tutorial/Wmml.pmod
+++ b/tutorial/Wmml.pmod
@@ -4,6 +4,36 @@ import ".";
 #endif /* __VERSION__ >= 0.6 */
 import Sgml;
 
+/*
+ * My dilemma:
+ *
+ * WMML is not a very good 'in between'-format because it
+ * does not allow to send structured mappings to the output
+ * generators. Because of this the output generator has to
+ * do extensive parsing to find the proper structure elements
+ * *OR* it becomes dependant on the order that the data is
+ * delivered to it, which is *not* good.
+ *
+ * Example:
+ * <function><man_title>bla bla</man_title><man_desc>WMML DATA</man_desc></man_desc>
+ * Would be easier for the output generator to parse as:
+ * <function (["man_title":({"bla bla"}), "man_desc":WMML DATA ])>
+ *
+ * Possible solution one:
+ * Create a link in the properties mapping to the WMML segment in question,
+ * the result of the above would be:
+ *   X=Tag("man_title",([]),0,({"bla bla"}));
+ *   Y=Tag("man_desc",([]),0,WMML DATA);
+ *   Tag("function",(["<man_title>":X,"man_desc":Y]),0,({X,Y}));
+ * advantages of this method:
+ *   backwards compatible (with most things)
+ * disadvantages of this method:
+ *
+ * Solution two:
+ *   Same as above, but using another field in the Tag class.
+ *
+ */
+
 SGML low_make_concrete_wmml(SGML data);
 
 class Trace
@@ -208,7 +238,7 @@ INDEX_DATA collect_index(SGML data, void|INDEX_DATA index,void|mapping taken)
     if(objectp(data))
     {
       if(data->tag == "anchor"
-#if 1 // Let's try to add these to the 
+#if 0 // Let's try to add these to the 
 	  && !data->params->type
 #endif
 	)
@@ -608,8 +638,9 @@ SGML fix_section(TAG t, object(Enumerator) e)
   TAG ret=Tag(t->tag,
 	      t->params+(["number":num]),
 	      t->pos,
-	      t->data=low_make_concrete_wmml(t->data),
+	      low_make_concrete_wmml(t->data),
 	      t->file);
+
   toker->pop(ret);
 
   currentE->pop();
@@ -618,31 +649,214 @@ SGML fix_section(TAG t, object(Enumerator) e)
   return fix_anchors(ret);
 }
 
-SGML fix_class(TAG t, string name)
+array(array(string)) fix_names(Tag tag)
+{
+  array anchors=({}),fullnames=({});
+  string last;
+  
+  foreach ( replace(tag->params->name,
+			    ({"&gt;","&lt;"}),({">","<"}))/",",
+		   string name)
+    {
+      string fullname;
+      if (name!="" && name[0]=='.')
+	fullname=last+name[1..];
+      else if (name[0..strlen(classbase->query())-1]==
+	       classbase->query() ||
+	       tag->params->fullpath)
+	fullname=name;
+      else switch(tag->tag)
+      {
+	case "class":
+	case "module":
+	case "method":
+	case "variable":
+	  fullname=classbase->query()+"."+name; // -> ?
+	  break;
+	case "function":
+	case "constant":
+	  fullname=classbase->query()+"."+name;
+	  break;
+      }
+      anchors+=({name_to_link(fullname)});
+      fullnames+=({fullname});
+      last=reverse(array_sscanf(reverse(fullname),"%*[^.>]%s")[0]);
+    }
+  return ({anchors, fullnames});
+}
+
+SGML mkheader(TAG tag, array(string) fullnames, array(string) anchors)
+{
+#if 1
+  array res=
+    ({Tag("man_title",(["title":upper_case(tag->tag)]),
+	  tag->pos,
+	  Array.map(
+	    fullnames,
+	    lambda(string name,int pos)
+	    { return ({Tag("tt",([]),pos,({name}))}); },
+	    tag->pos)
+	  *({ ",", Tag("br") })
+	  +({ (tag->params->title
+	       ?" - "+tag->params->title
+	       :"")}))
+    }) + tag->data;
+#else
+
+  /* This would probably look nicer, but it needs to be fixed... */
+  SGML res= ({
+    Tag("table",(["border":"0","wmml-type":tag->tag]),tag->pos,({
+      Tag("tr",0,tag->pos,({
+	Tag("td",0,tag->pos,
+	  Array.map(
+	    fullnames,
+	    lambda(string name,int pos)
+	    {
+	      return ({Tag("h2",([]),tag->pos,({name}))});
+	    })
+	    *({ Tag("br") })
+	  ),
+	Tag("td",0,tag->pos,
+	    ({ (tag->params->title ?" - "+tag->params->title :"")})
+	  ),
+      }))
+    }) ) }) + tag->data;
+#endif
+  
+  res=
+    ({Tag(tag->tag,(["name":fullnames*", ",
+		    "title":tag->params->title]),tag->pos,
+	  low_make_concrete_wmml(res))});
+  
+  // FIXME:
+  // The replace "->" to "."
+  // in here is kludgy and might not be correct,
+  // check for accuracy....
+  // -Hubbe
+  foreach (anchors,string anchor)
+    res=({Tag("anchor",(["name":replace(anchor,"->",".")]),
+	      tag->pos,res)});
+  
+  return res;
+}
+
+SGML fix_class(TAG tag, string name)
 {
+  array(string) anchors, fullnames;
+  [anchors, fullnames]=fix_names(tag);
+
   classbase->push(name);
-  TAG ret=Tag(t->tag,
-	      t->params+(["name":classbase->query()]),
-	      t->pos,
-	      t->data=low_make_concrete_wmml(t->data),
-	      t->file);
 
-  SGML ret=
+#if 0
+  /* I wish I remember what this magic is for -Hubbe */
+  TAG foo=Tag(tag->tag,
+	      tag->params+(["name":classbase->query()]),
+	      tag->pos,
+	      tag->data=low_make_concrete_wmml(tag->data),
+	      tag->file);
+
+  SGML res=
   ({
     Tag("anchor",
-	(["name":classbase->query(),"type":t->tag]),
-	t->pos,
-	({t}),
-	t->file)
+	(["name":classbase->query(),"type":tag->tag]),
+	tag->pos,
+	({tag}),
+	tag->file)
       });
+#else
+  SGML res=mkheader(tag, fullnames, anchors);
+#endif
   classbase->pop();
-  return ret;
+  return res;
+}
+
+SGML fix_module(TAG tag, string name)
+{
+  array(string) anchors, fullnames;
+  [anchors, fullnames]=fix_names(tag);
+
+  classbase->push(name);
+
+#if 1
+  /* I wish I remember what this magic is for -Hubbe */
+  TAG foo=Tag(tag->tag,
+	      tag->params+(["name":classbase->query()]),
+	      tag->pos,
+	      tag->data=low_make_concrete_wmml(tag->data),
+	      tag->file);
+
+  SGML res=
+  ({
+    Tag("anchor",
+	(["name":classbase->query(),"type":tag->tag]),
+	tag->pos,
+	({tag}),
+	tag->file)
+      });
+#else
+  SGML res=mkheader(tag, fullnames, anchors);
+#endif
+  classbase->pop();
+  return res;
+}
+
+#define TNAME(X) (objectp(X) ? X->tag : "")
+#define PROCESS(X,T) foreach(X,TAG T) switch(objectp(T) ? T->tag : "")
+
+
+SGML explode(SGML data, multiset tags)
+{
 }
 
 SGML low_make_concrete_wmml(SGML data)
 {
   if(!data) return 0;
   SGML ret=({});
+  SGML tmp=({});
+
+#if 1
+  /* This part is intended to convert <p/> to <p> ... </p>
+   * Hmm, maybe we should encapsulate *all* paragraphs in <p></p> ?
+   * (But how to we recognize am unmarked paragraph as opposed to
+   *  an argument? Example the text within <man_see></man_see> should
+   *  *NOT* be in a <p>)
+   */
+  PROCESS(reverse(data), ptag)
+    {
+      default:
+	tmp+=({ptag});
+	break;
+
+      case "p":
+	ret+=({
+	  Tag(ptag->tag,
+	      ptag->params,
+	      ptag->pos,
+	      reverse(tmp),
+	      ptag->file)
+	});
+	tmp=({});
+	break;
+
+      case "h1":
+      case "h2":
+      case "h3":
+      case "h4":
+      case "h5":
+      case "h6":
+      case "center":
+      case "dl":
+      case "ul":
+      case "ol":
+	tmp+=({ptag});
+	ret+=tmp;
+	tmp=({});
+    }
+  ret+=tmp;
+  data=reverse(ret);
+
+  ret=({});
+#endif
 
   foreach(data, TAG tag)
   {
@@ -652,6 +866,44 @@ SGML low_make_concrete_wmml(SGML data)
     }else if (objectp(tag)) {
       switch(tag->tag)
       {
+	case "dl":
+	case "ul":
+	case "ol":
+	{
+	  array tmp2=({});
+	  tmp=({});
+	    
+	  PROCESS(reverse(tag->data), t)
+	    {
+	      default:
+		tmp+=({t});
+		break;
+		
+	      case "li":
+	      case "dt":
+	      case "dd":
+		tmp2+=({
+		  Tag(t->tag,
+		      t->params,
+		      t->pos,
+		      low_make_concrete_wmml(reverse(tmp)),
+		      t->file)
+		});
+		tmp=({});
+	    }
+
+	  if(strlen(replace(Sgml.get_text(tmp),({" ","\t","\n","\r"}),({"","","",""}))))
+	  {
+	    werror("WARNING, data ignored in %s near %s\n",tag->tag,tag->location());
+	  }
+	  ret+=({Tag(tag->tag,
+		     tag->params,
+		     tag->pos,
+		     low_make_concrete_wmml(reverse(tmp2)),
+		     tag->file)});
+	  continue;
+	}
+	  
 	case "index":
 	case "table-of-contents":
 	  ret+=({
@@ -751,7 +1003,6 @@ SGML low_make_concrete_wmml(SGML data)
 	  continue;
 	  
 	case "class":
-	case "module":
 	{
 	   string name=tag->params->name;
 	   if (!name)
@@ -764,6 +1015,20 @@ SGML low_make_concrete_wmml(SGML data)
 	   ret+=fix_class(tag, name);
 	   continue;
 	}
+
+	case "module":
+	{
+	   string name=tag->params->name;
+	   if (!name)
+	   {
+	      werror("module or class w/o name\n"+
+		     tag->location()+"\n");
+	      name="(unknown)";
+	   }
+	   sscanf(name,classbase->query()+"%*[.->]%s",name);
+	   ret+=fix_module(tag, name);
+	   continue;
+	}
 	
 	case "man_syntax":
 	case "man_example":
@@ -844,37 +1109,10 @@ SGML low_make_concrete_wmml(SGML data)
 	case "function":
         case "constant":
 	{
-	   array anchors=({}),fullnames=({});
-	   string last;
+	  array(string) anchors, fullnames;
+	  [anchors, fullnames]=fix_names(tag);
 
-	   foreach (replace(tag->params->name,
-			    ({"&gt;","&lt;"}),({">","<"}))/",",
-                    string name)
-	   {
-	      string fullname;
-	      if (name!="" && name[0]=='.')
-		 fullname=last+name[1..];
-	      else if (name[0..strlen(classbase->query())-1]==
-		  classbase->query() ||
-		  tag->params->fullpath)
-		 fullname=name;
-	      else switch(tag->tag)
-	      {
-		 case "method":
-	         case "variable":
-		    fullname=classbase->query()+"."+name; // -> ?
-		    break;
-		 case "function":
-	         case "constant":
-		    fullname=classbase->query()+"."+name;
-		    break;
-	      }
-	      anchors+=({name_to_link(fullname)});
-	      string tlast=
-		 reverse(array_sscanf(reverse(fullname),"%*[^.>]%s")[0]);
-	      fullnames+=({fullname});
-	      last=reverse(array_sscanf(reverse(fullname),"%*[^.>]%s")[0]);
-	   }
+#if 0
 	   array res=
 	     ({Tag("man_title",(["title":upper_case(tag->tag)]),
 		   tag->pos,
@@ -888,7 +1126,7 @@ SGML low_make_concrete_wmml(SGML data)
 			?" - "+tag->params->title
 			:"")}))
 	     }) + tag->data;
-		   
+
 	   res=
 	      ({Tag(tag->tag,(["name":fullnames*", ",
 			       "title":tag->params->title]),tag->pos,
@@ -897,8 +1135,10 @@ SGML low_make_concrete_wmml(SGML data)
 	   foreach (anchors,string anchor)
 	      res=({Tag("anchor",(["name":anchor]),
 			tag->pos,res)});
-
 	   ret+=res;
+#else
+	   ret+=mkheader(tag, anchors, fullnames);
+#endif
 
 	   continue;
 	}