diff --git a/tutorial/Html.pmod b/tutorial/Html.pmod
index dbc7f62417df7d1fe89f23bf572d1ae673294dfc..3097bb70ff42e0f0fa248ac468909b9de65ae92a 100644
--- a/tutorial/Html.pmod
+++ b/tutorial/Html.pmod
@@ -53,10 +53,25 @@ string mktag(string tag, mapping params)
   string ret="<"+tag;
   foreach(indices(params),string i)
   {
-    ret+=" "+quote_param(i);
+    ret+=" "+i;
 
     if(stringp(params[i]))
-      ret+="='"+quote_param(params[i])+"'";
+    {
+      switch(i)
+      {
+	case "href":
+	  ret+="='"+quote_param(params[i])+"'";
+	  break;
+
+	default:
+	  if(search(params[i],"\"")==-1)
+	    ret+="=\""+params[i]+"\"";
+	  else if(search(params[i],"'")==-1)
+	    ret+="='"+params[i]+"'";
+	  else
+	    ret+="=\""+replace(params[i],"\"","'")+"\"";
+      }
+    }
   }
   return ret+">";
 }
diff --git a/tutorial/Makefile b/tutorial/Makefile
index 0a6322abbb524639f3a6010344aeef8b02a90540..aaff6c4ec725df065a74a21e3f00e24950f9501a 100644
--- a/tutorial/Makefile
+++ b/tutorial/Makefile
@@ -8,6 +8,9 @@ tutorial.html: tutorial.wmml
 tutorial_onepage.html: tutorial.wmml
 	./wmmltohtml2 <tutorial.wmml html_onepage tutorial_onepage
 
+clean:
+	rm *.html illustration_cache illustration*.gif
+
 # tutorial.html: tutorial.wmml wmml_to_html
 #	./wmml_to_html <tutorial.wmml >tutorial.html
 
diff --git a/tutorial/Sgml.pmod b/tutorial/Sgml.pmod
index d3e1a51b33ec82663a37fa7b3d5b24ed8d73a6be..9515b737f44163b02e6ca7337f8cfa0a3fcc7ae5 100644
--- a/tutorial/Sgml.pmod
+++ b/tutorial/Sgml.pmod
@@ -109,6 +109,7 @@ SGML lex(string data, string file)
       }
     }
 
+//    werror("Fount tag "+tag+" at pos "+pos+".\n");
     ret+=({ Tag(tag,params,pos,0,file), unquote(s) });
     pos+=sizeof(foo[e]);
   }
@@ -145,24 +146,38 @@ SGML group(SGML data)
 }
 
 
-string generate(SGML data)
+
+string mktag(string tag, mapping params)
+{
+  string ret="<"+tag;
+  foreach(indices(params),string i)
+  {
+    ret+=" "+i;
+
+    if(stringp(params[i]))ret+="="+params[i];
+  }
+  return ret+">";
+}
+
+varargs string generate(SGML data, function mkt)
 {
   string ret="";
+  if(!mkt)
+  {
+    werror("ARNING");
+    mkt=mktag;
+  }
   foreach(data, TAG foo)
     {
       if(stringp(foo))
       {
 	ret+=quote(foo);
       }else{
-	ret+="<"+foo->tag;
-	foreach(indices(foo->params), string name)
-	  ret+=" "+name+"="+foo->params[name];
-
-	ret+=">";
+	ret+=mkt(foo->tag,foo->params);
 	if(foo->data)
 	{
-	  ret+=generate(foo->data);
-	  ret+="</"+foo->tag+">";
+	  ret+=generate(foo->data,mkt);
+	  ret+=mkt("/"+foo->tag,([]));
 	}
       }
     }
diff --git a/tutorial/Wmml.pmod b/tutorial/Wmml.pmod
index ae86e35605f2871b777532007a878be94a9257dc..8767aef21db58d87fd2a673fc4f88c5acd73e032 100644
--- a/tutorial/Wmml.pmod
+++ b/tutorial/Wmml.pmod
@@ -1,5 +1,7 @@
 #include "types.h"
-impoert Sgml;
+import Sgml;
+
+SGML low_make_concrete_wmml(SGML data);
 
 static private int verify_any(SGML data, string in)
 {
@@ -114,23 +116,6 @@ int verify(SGML data)
   return verify_any(data,"");
 }
 
-int islink(string tag)
-{
-  switch(tag)
-  {
-  case "anchor":
-  case "chapter":
-  case "preface":
-  case "introduction":
-  case "section":
-  case "table":
-  case "appendix":
-  case "image":
-  case "illustration":
-    return 1;
-  }
-}
-
 INDEX_DATA collect_index(SGML data, void|INDEX_DATA index,void|mapping taken)
 {
   if(!index) index=([]);
@@ -140,7 +125,7 @@ INDEX_DATA collect_index(SGML data, void|INDEX_DATA index,void|mapping taken)
   {
     if(objectp(data))
     {
-      if(islink(data->tag))
+      if(data->tag == "anchor" && !data->params->type)
       {
 	if(string real_name=data->params->name)
 	{
@@ -370,19 +355,158 @@ string name_to_link(string x)
   return replace(x,({"->","-&gt;"}),({".","."}));
 }
 
-SGML metadata=({});
-
 class Wmml
 {
   SGML metadata;
-  SGML toc_data;
-  SGML index_data;
+  TOC toc;
+  INDEX_DATA index_data;
   SGML data;
 };
 
-SGML low_make_concrete_wmml(SGML data,
-			    string classbase,
-			    string *current)
+class Enumerator
+{
+  string *base;
+
+  object push() { base+=({"1"}); return this_object(); }
+  object pop()  { base=base[..sizeof(base)-2]; return this_object();  }
+  object inc() 
+  {
+    switch(base[-1][0])
+    {
+      case '0'..'9':
+	base[-1]=(string)( 1+ (int) base[-1]);
+	break;
+
+      default:
+	base[-1]=sprintf("%c",base[-1][0]+1);
+    }
+
+    return this_object();
+  }
+
+  string query()
+  {
+    return base*".";
+  }
+
+  void create(mixed b)
+  {
+    if(objectp(b)) b=b->base;
+    if(!arrayp(b)) b=({b});
+    base=b;
+  }
+};
+
+class Stacker
+{
+  inherit Enumerator;
+
+  object push(string what) { base+=({what}); return this_object(); }
+  object pop()  { base=base[..sizeof(base)-2]; return this_object();  }
+
+  void create(void|mixed b)
+  {
+    ::create(b||({}));
+  }
+};
+
+class TocBuilder
+{
+  import Sgml;
+
+  TOC *stack=({ ({}) });
+
+  void push() { stack+=({ ({}) });  }
+
+  void pop(TAG t)
+  {
+    stack[-2]+=({
+      Tag(t->tag+"_toc",
+	  t->params+([]),
+	  t->pos,
+	  stack[-1],
+	  t->file)
+    });
+    stack=stack[..sizeof(stack)-2];
+  }
+
+  TOC query() { return stack[0]; }
+};
+
+
+SGML metadata;
+object(Enumerator) currentE;
+object(Enumerator) appendixE;
+object(Enumerator) chapterE;
+object(Stacker) classbase;
+object(TocBuilder) toker;
+
+SGML fix_anchors(TAG t)
+{
+  TAG ret=t;
+  if(t->params->number)
+  {
+    ret=Tag("anchor",
+	    (["name":t->params->number,"type":t->tag]),
+	    t->pos,
+	    ({ret}),
+	    t->file);
+  }
+
+  if(t->params->name)
+  {
+    ret=Tag("anchor",
+	    (["name":t->params->name,"type":t->tag]),
+	    t->pos,
+	    ({ret}),
+	    t->file);
+  }
+  return ({ret});
+}
+
+SGML fix_section(TAG t, object(Enumerator) e)
+{
+  object(Enumerator) save=currentE;
+  string num=e->query();
+  e->push();
+  currentE=e;
+
+  toker->push();
+
+  TAG ret=Tag(t->tag,
+	      t->params+(["number":num]),
+	      t->pos,
+	      t->data=low_make_concrete_wmml(t->data),
+	      t->file);
+  toker->pop(ret);
+
+  currentE->pop();
+  currentE=save;
+
+  return fix_anchors(ret);
+}
+
+SGML fix_class(TAG t, string name)
+{
+  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);
+
+  classbase->pop();
+
+  return ({
+    Tag("anchor",
+	(["name":classbase->query(),"type":t->tag]),
+	t->pos,
+	({t}),
+	t->file)
+      });
+}
+
+SGML low_make_concrete_wmml(SGML data)
 {
   if(!data) return 0;
   SGML ret=({});
@@ -395,6 +519,27 @@ SGML low_make_concrete_wmml(SGML data,
     }else{
       switch(tag->tag)
       {
+	case "index":
+	case "table-of-contents":
+	  ret+=({
+	    Tag("anchor",
+		(["name":tag->params->name || tag->tag]),
+		tag->pos,
+		({
+		  Tag(tag->tag,
+		      tag->params,
+		      tag->pos,
+		      low_make_concrete_wmml(tag->data),
+		      tag->file),
+		    }),
+		tag->file,
+		)
+	      });
+	  toker->push();
+	  toker->pop(tag);
+	  continue;
+
+
 	case "head":
 	  metadata+=tag->data;
 	  continue;
@@ -403,21 +548,32 @@ SGML low_make_concrete_wmml(SGML data,
 	{
 	  string filename=tag->params->file;
 	  SGML tmp=group(lex(Stdio.read_file(filename),filename));
-	  ret+=low_make_concrete_wmml(tmp,classbase);
+	  ret+=low_make_concrete_wmml(tmp);
 	  continue;
 	}
 	  
-	case "section":
 	case "chapter":
+	  ret+=fix_section(tag,chapterE);
+	  chapterE->inc();
+	  continue;
+
+	case "section":
+	  ret+=fix_section(tag,currentE);
+	  currentE->inc();
+	  continue;
+
 	case "preface":
+	  ret+=fix_section(tag,Enumerator("preface"));
+	  continue;
+
 	case "introduction":
-	case "appendix":
-	  switch(tag->t)
-	  {
-	    tag->params->number=current*".";
-	    current[-1]=(string)(1+(int)current[-1]);
-	  }
+	  ret+=fix_section(tag,Enumerator("introduction"));
+	  continue;
 
+	case "appendix":
+	  ret+=fix_section(tag,appendixE);
+	  appendixE->inc();
+	  continue;
 	  
 	case "table":
 	case "image":
@@ -427,9 +583,7 @@ SGML low_make_concrete_wmml(SGML data,
 	    TAG t=Tag(tag->tag,
 		      tag->params,
 		      tag->pos,
-		      tag->data=low_make_concrete_wmml(tag->data,
-						       current,
-						       classbase),
+		      tag->data=low_make_concrete_wmml(tag->data),
 		      tag->file);
 	    ret+=({
 	      Tag("anchor",
@@ -443,21 +597,8 @@ SGML low_make_concrete_wmml(SGML data,
 	  
 	case "class":
 	case "module":
-	{
-	  string tmp=classbase;
-	  if(!classbase || classbase=="")
-	  {
-	    classbase=tag->params->name;
-	  }else{
-	    classbase+="."+tag->params->name;
-	  }
-	  ret+=({
-	    Tag("anchor",(["name":classbase,"type":tag->tag]),tag->pos,
-		low_make_concrete_wmml(tag->data))
-	      });
-	  classbase=tmp;
+	  ret+=fix_class(tag, tag->params->name);
 	  continue;
-	}
 	
 	case "man_syntax":
 	case "man_example":
@@ -514,10 +655,10 @@ SGML low_make_concrete_wmml(SGML data,
 	  switch(tag->tag)
 	  {
 	    case "method":
-	      fullname=classbase+"->"+tag->params->name;
+	      fullname=classbase->query()+"->"+tag->params->name;
 	      break;
 	    case "function":
-	      fullname=classbase+"."+tag->params->name;
+	      fullname=classbase->query()+"."+tag->params->name;
 	      break;
 	  }
 	  ret+=low_make_concrete_wmml(({
@@ -570,6 +711,22 @@ SGML low_make_concrete_wmml(SGML data,
   return ret;
 }
 
+object(Wmml) make_concrete_wmml(SGML data)
+{
+  classbase=Stacker();
+  currentE=0;
+  appendixE=Enumerator("A");
+  chapterE=Enumerator("1");
+  toker=TocBuilder();
+  object(Wmml) ret= Wmml();
+  metadata=({});
+  ret->data=low_make_concrete_wmml(data);
+  ret->index_data=collect_index(ret->data);
+  ret->toc=toker->query();
+  ret->metadata=metadata;
+  return ret;
+}
+
 void save_image_cache();
 
 int gifnum;
@@ -715,131 +872,3 @@ void create()
   }
 }
 
-int chapters;
-int appendices;
-
-static private SGML low_collect_toc(mixed *data,
-				    string prefix,
-				    int *current)
-{
-  SGML ret=({});
-
-  foreach(data, TAG t)
-    {
-      if(objectp(t))
-      {
-	switch(t->tag)
-	{
-	case "section":
-	  t->params->number=prefix+(string)current[-1];
-	  
-	  ret+=({
-	    Tag("section_toc",
-		     t->params,
-		     t->pos,
-		     low_collect_toc(t->data,
-				 t->params->number+".",
-				 current+({1})))
-	      });	      ;
-	  current[-1]++;
-	  break;
-
-	case "chapter":
-	  if(current)
-	    werror("Chapter inside chapter/appendix near "+t->pos+".\n");
-	  t->params->number=(string)chapters;
-
-	  ret+=({
-	    Tag("chapter_toc",
-		     t->params,
-		     t->pos,
-		     low_collect_toc(t->data,
-				 t->params->number+".",
-				 ({1})))
-	      });
-	  chapters++;
-	  break;
-	  
-	case "appendix":
-	  if(current)
-	    werror("Appendix inside chapter/appendix near "+t->pos+".\n");
-	  
-	  t->params->number=sprintf("%c",appendices);
-	  
-	  ret+=({
-	    Tag("appendix_toc",
-		     t->params,
-		     t->pos,
-		     low_collect_toc(t->data,
-				 t->params->number+".",
-				 ({1}))),
-	      });
-	  appendices++;
-	  break;
-
-	case "preface":
-	  if(current)
-	    werror("Preface inside chapter/appendix near "+t->pos+".\n");
-
-	  t->params->number="preface";
-	  
-	  ret+=({
-	    Tag("preface_toc",
-		     t->params,
-		     t->pos,
-		     low_collect_toc(t->data,
-				 t->params->number+".",
-				 ({1}))),
-	      });
-	  break;
-
-	case "introduction":
-	  if(current)
-	    werror("Introduction inside chapter/appendix near "+t->pos+".\n");
-
-	  t->params->number="introduction";
-	  
-	  ret+=({
-	    Tag("introduction_toc",
-		     t->params,
-		     t->pos,
-		     low_collect_toc(t->data,
-				 t->params->number+".",
-				 ({1}))),
-	      });
-	  break;
-
-	case "index":
-	case "table-of-contents":
-	  t->params->number=t->tag;
-	  ret+=({
-	    Tag(t->tag+"_toc",
-		     t->params,
-		     t->pos)
-	      });
-	  break;
-
-
-	default:
-	  if(t->data)
-	    ret+=low_collect_toc(t->data,prefix,current);
-	}
-      }
-    }
-  return ret;
-}
-
-SGML sort_toc(SGML toc)
-{
-  // Assume correct order
-  return toc;
-}
-
-SGML collect_toc(SGML data)
-{
-  SGML toc;
-  chapters=1;
-  appendices='A';
-  toc=low_collect_toc(data,"",0);
-  return sort_toc(toc);
-}
diff --git a/tutorial/html.pike b/tutorial/html.pike
index 4f61cce2f17edb948e162e7bfb650e0c829ab55e..44ec5a870e2707ac3cb0b8a9978f0446381f8dd0 100644
--- a/tutorial/html.pike
+++ b/tutorial/html.pike
@@ -36,6 +36,34 @@ string *srt(string *x)
   return x;
 }
 
+int useful_tag(TAG t)
+{
+  return !stringp(t) || sscanf(t,"%*[ \n\r\t�]%*c")==2;
+}
+
+TAG get_tag(TAG t)
+{
+  while(1)
+  {
+    switch(t->tag)
+    {
+      default: return t;
+
+      case "a":
+      case "anchor":
+    }
+    if(!t->data) return t;
+
+    SGML x=Array.filter(t->data,useful_tag);
+    if(sizeof(x)==1 && objectp(t->data[0]))
+      t=t->data[0];
+    else
+      break;
+  }
+
+  return t;
+}
+
 void add_target_to_links(SGML foo, string target)
 {
   foreach(foo, TAG t)
@@ -101,7 +129,10 @@ varargs SGML low_toc_to_wmml(SGML toc)
 	name=0;
 	link=0;
 	title="Appendices";
-	break;
+	ret+=({Sgml.Tag("dt",([]),t->pos),
+		 " "+title+"\n"})+
+	  low_toc_to_wmml(t->data);
+	continue;
 	
       case "appendix_toc":
 	name="Appendix "+t->params->number;
@@ -287,7 +318,7 @@ SGML convert(SGML data)
 	    werror("Warning: Cannot find ref "+to+" (near pos "+data->pos+")\n");
 	  }
 	  if(t2)
-	    data->data=({t2->tag+" "+t2->params->number});
+	    data->data=({t2->tag+" "+t2->params->number+" \""+t2->params->title+"\""});
 	  else
 	    data->data=({"unknown"});
 	  data->tag="a";
@@ -506,6 +537,7 @@ SGML wmml_to_html(SGML data)
       });
 }
 
+
 SGML low_split(SGML data)
 {
   SGML current=({});
@@ -513,7 +545,8 @@ SGML low_split(SGML data)
     {
       if(objectp(t))
       {
-	switch(t->tag)
+	TAG t2=get_tag(t);
+	switch(t2->tag)
 	{
 	case "preface":
 	  if(!sections->introduction)
@@ -543,9 +576,12 @@ SGML low_split(SGML data)
 	  continue;
 
 	case "index":
+	  sections[t2->params->name || "index"]=({ t });
+	  continue;
+
 	case "chapter":
 	case "appendix":
-	  sections[t->params->number]=({ t });
+	  sections[t2->params->number]=({ t });
 	  continue;
 
 	case "firstpage":
@@ -576,7 +612,8 @@ SGML low_split(SGML data)
 	  });
 
 	  sections->toc_frame=Sgml.copy(({ t }));
-	  sections->toc_frame[0]->params->target="display";
+	  TAG t3=get_tag(sections->toc_frame[0]);
+	  t3->params->target="display";
 	  sections->toc_frame[0]->params->name="toc_frame";
 	  break;
 
@@ -591,65 +628,22 @@ SGML low_split(SGML data)
   return current;
 }
 
-void de_abstract_anchors(SGML data)
-{
-  for(int e=0;e<sizeof(data);e++)
-  {
-    TAG t=data[e];
-    if(objectp(t))
-    {
-      if(Wmml.islink(t->tag))
-      {
-	if(string tmp=t->params->name)
-	  data[e]=Sgml.Tag("anchor",(["name":tmp]),t->pos,({data[e]}));
-
-	if(string tmp=t->params->number)
-	  data[e]=Sgml.Tag("anchor",(["name":tmp]),t->pos,({data[e]}));
-      }else{
-	switch(t->tag)
-	{
-	case "index":
-	case "preface":
-	case "introduction":
-	case "table-of-contents":
-	  data[e]=Sgml.Tag("anchor",
-			   ([
-			     "name":t->namet || t->tag
-			     ]),t->pos,({data[e]}));
-	}
-      }
-
-      if(t->data)
-	de_abstract_anchors(t->data);
-    }
-  }
-}
-
-
 void low_collect_links(SGML data, string file)
 {
   foreach(data,TAG t)
     {
       if(objectp(t))
       {
-	if(Wmml.islink(t->tag))
+	if(t->tag == "anchor")
 	{
 	  if(t->params->name)
 	  {
 	    link_to_page[t->params->name]=file;
-	    link_to_data[t->params->name]=t;
+	    link_to_data[t->params->name]=get_tag(t);
 	  }
 	  if(t->params->number)
 	    link_to_page[t->params->number]=file;
 	}
-	switch(t->tag)
-	{
-	case "index":
-	case "introduction":
-	case "preface":
-	case "table-of-contents":
-	  link_to_page[t->params->name || t->tag]=file;
-	}
 
 	if(t->data)
 	  low_collect_links(t->data,file);
@@ -684,13 +678,13 @@ string prevify(string num)
   return tmp*".";
 }
 
-void output(string base, SGML data, SGML toc, INDEX_DATA index_data)
+void output(string base, WMML data)
 {
   basename=base;
 
   werror("Splitting ");
   sections=([]);
-  sections[""]=low_split(data);
+  sections[""]=low_split(data->data);
 
   werror("Finding links ");
   foreach(indices(sections), string file)
@@ -704,7 +698,8 @@ void output(string base, SGML data, SGML toc, INDEX_DATA index_data)
       string tmp1;
       if(sizeof(data)>0 && objectp(data[0]))
       {
-	switch(data[0]->tag)
+	TAG t2=get_tag(data[0]);
+	switch(t2->tag)
 	{
 	  string name;
 	  string to;
@@ -715,20 +710,22 @@ void output(string base, SGML data, SGML toc, INDEX_DATA index_data)
 	  case "appendix":
 	  case "section":
 	  case "introduction":
-	  tmp1=data[0]->params->number;
+	  tmp1=t2->params->number;
 
 	  
 	  if(sections[to=prevify(tmp1)])
 	  {
-	    name="Previous "+data[0]->tag;
+	    name="Previous "+t2->tag;
 	  }
 	  
 	  if(name && sections[to])
 	  {
 	    links+=({ Sgml.Tag("a",(["href":mkfilename(to)]),0,
 			       ({
-				 Sgml.Tag("img",(["src":"left.gif",
-					       "border":"0"])),
+				 Sgml.Tag("img",([
+				   "src":"left.gif",
+				   "alt":" < ",
+				   "border":"0"])),
 				 name,
 			       })),
 		      "\n",
@@ -738,8 +735,11 @@ void output(string base, SGML data, SGML toc, INDEX_DATA index_data)
 
 	  links+=({ Sgml.Tag("a",(["href":mkfilename("")]),0,
 			     ({
-			       Sgml.Tag("img",(["src":"up.gif",
-					       "border":"0"])),
+			       Sgml.Tag("img",
+					([
+					  "src":"up.gif",
+					  "alt":" ^ ",
+					 "border":"0"])),
 			       "To contents",
 			     })),
 		      "\n",
@@ -750,9 +750,9 @@ void output(string base, SGML data, SGML toc, INDEX_DATA index_data)
 
 	  if(sections[to=nextify(tmp1)])
 	  {
-	    name="Next "+data[0]->tag;
+	    name="Next "+t2->tag;
 	  }else{
-	    switch(data[0]->tag)
+	    switch(t2->tag)
 	    {
 	      case "chapter": name="To appendices"; to="A"; break;
 	      case "appendix": name="To index"; to="index"; break;
@@ -767,8 +767,10 @@ void output(string base, SGML data, SGML toc, INDEX_DATA index_data)
 	  {
 	    links+=({ Sgml.Tag("a",(["href":mkfilename(to)]),0,
 			       ({
-				 Sgml.Tag("img",(["src":"right.gif",
-					       "border":"0"])),
+				 Sgml.Tag("img",([
+				   "src":"right.gif",
+				   "alt":" > ",
+				   "border":"0"])),
 				 name,
 			       })),
 		      "\n",
@@ -793,10 +795,10 @@ void output(string base, SGML data, SGML toc, INDEX_DATA index_data)
 
 
   werror("Converting TOC to WMML\n");
-  html_toc=toc_to_wmml(toc);
+  html_toc=toc_to_wmml(data->toc);
 
   werror("Converting index to WMML\n");
-  INDEX index=Wmml.group_index(index_data);
+  INDEX index=Wmml.group_index(data->index_data);
   index=Wmml.group_index_by_character(index);
   html_index=index_to_wmml(index);
   index=0;
@@ -805,11 +807,10 @@ void output(string base, SGML data, SGML toc, INDEX_DATA index_data)
     {
       string filename=mkfilename(file);
       werror("Anchoring ");
-      de_abstract_anchors(sections[file]);
       werror(filename+": WMML->HTML");
-      data=wmml_to_html(sections[file]);
+      SGML data=wmml_to_html(sections[file]);
       werror("->String");
-      string data=Sgml.generate(data);
+      string data=Sgml.generate(data,Html.mktag);
       werror("->disk");
       out::open(filename,"wct");
       out::write(data);
diff --git a/tutorial/tutorial.wmml b/tutorial/tutorial.wmml
index e0ad6db6d440ad70237070c8c114e76c64442027..6c61c26c0e8f2c5f245e325974a0884855142cb0 100644
--- a/tutorial/tutorial.wmml
+++ b/tutorial/tutorial.wmml
@@ -32,7 +32,9 @@ extensions to Pike. I have been trying for years to get someone else to
 write this book, but since it seems impossible without paying a fortune for
 it I will have to do it myself. 
 A big thanks goes to
-<a href="http://www.emit.com.pl/ian.html">Ian Carr-de Avelon</a> for helping
+<a href="http://www.emit.com.pl/ian.html">Ian Carr-de Avelon</a> and
+<a href="mailto:hedda@idonix.se">Henrik Wallin</a>
+ for helping
 me iron out some of the rough spots. 
 
 The book assumes that
@@ -176,7 +178,7 @@ data type.
 <chapter title="Getting started">
 <p>
 First you need to have Pike installed on your computer. See <ref to=install>
-"how to install Pike" if this is not already done. It is also vital
+ if this is not already done. It is also vital
 for the first of the following examples that the Pike binary is in your UNIX search
 path. If you have problems with this, consult the manual for your shell
 or go buy a beginners book about UNIX.
@@ -4480,7 +4482,7 @@ a slow machine available for the server.
 </chapter>
 </module>
 
-<anchor name=Threads>
+<module name=Threads>
 <chapter title="Threads">
 Threads are used to run several Pike functions at the same time without having to start
 several Pike processes. Using threads often simplifies coding and because the
@@ -4597,16 +4599,12 @@ this example again.
 This section describes all thread-related functions and classes.
 
 <hr noshade size=1>
-<anchor name=Thread.thread_create>
-<dl>
-<dt><encaps>NAME</encaps><dd>
-<tt>Thread.thread_create</tt> - create a thread
-<p>
-<dt><encaps>SYNTAX</encaps><dd>
-<tt>object thread_create(function <I>f</I>, mixed ... <I>args</I>);<br>
-</tt>
-<p>
-<dt><encaps>DESCRIPTION</encaps><dd>
+
+<function name=thread_create title="create a thread">
+<man_syntax>
+object thread_create(function <I>f</I>, mixed ... <I>args</I>);<br>
+</man_syntax>
+<man_description>
 This function creates a new thread which will run simultaneously
 to the rest of the program. The new thread will call the function
 <i>f</i> with the arguments <i>args</i>. When f returns the thread will cease
@@ -4614,37 +4612,25 @@ to exist. All Pike functions are 'thread safe' meaning that running
 a function at the same time from different threads will not corrupt
 any internal data in the Pike process. The returned value will be
 the same as the return value of this_thread() for the new thread.
-<p>
-<dt><encaps>NOTA BENE</encaps><dd>
+</man_description>
+<man_nb>
 This function is only available on systems with POSIX or UNIX threads support.
-<p>
-<dt><encaps>SEE ALSO</encaps><dd>
-<link to=Thread.Mutex>Thread.Mutex</link>, <link to=Thread.Condition>Thread.Condition</link> and <link to=Thread.this_thread>Thread.this_thread</link>
-<p>
-</dl>
+</man_nb>
+<man_see>Thread.Mutex, Thread.Condition, Thread.this_thread</man_see>
+</function>
 
-</anchor>
-<hr noshade size=1>
 
-<anchor name=Thread.this_thread>
-<dl>
-<dt><encaps>NAME</encaps><dd>
-<tt>Thread.this_thread</tt> - return thread id
-<p>
-<dt><encaps>SYNTAX</encaps><dd>
-<tt>object thread_id();<br>
-</tt>
-<p>
-<dt><encaps>DESCRIPTION</encaps><dd>
+<function name=this_thread title="return thread id">
+<man_syntax>
+object thread_id();<br>
+</man_syntax>
+<man_description>
 This function returns the object that identifies this thread.
-<p>
-<dt><encaps>SEE ALSO</encaps><dd>
-<link to=Thread.thread_create>Thread.thread_create</link>
-<p>
-</dl>
+</man_description>
+<man_see>Thread.thread_create</man_see>
+</function>
+
 
-</anchor>
-<hr noshade size=1>
 <anchor name=Thread.Mutex>
 <dl>
 <dt><encaps>NAME</encaps><dd>
@@ -5131,7 +5117,7 @@ on some UNIX systems. The above example does not work if your system does
 not have threads.
 </section>
 </chapter>
-</anchor>
+</module>
 
 <chapter title="Modules for specific data types">
 
@@ -12881,7 +12867,7 @@ init_module_programs are called to initialize it. When Pike exits
 exit_module is called in all dynamically loaded modules. These
 functions _must_ be available in the module.
 <p>Please see the source and any examples available at
-ftp://www.infovav.se/pub/pike for more information on how to
+ftp://www.idonex.se/pub/pike for more information on how to
 write modules for Pike in C.
 <p>
 <dt><encaps>BUGS</encaps><dd>
@@ -14887,20 +14873,21 @@ This is the BNF for Pike:
 <appendix title="How to install Pike" name=install>
 To install Pike, you need a C compiler, a couple of Mb of disk space,
 the source for Pike, and a bit of patience. The latest version of Pike is
-always available from <a href=http://pike.infovav.se>the Pike home page</a>.
+always available from <a href=http://pike.idonex.se>the Pike home page</a>.
 Lists of mirror sites and binary releases should also be available there.
 Pike should compile and install nicely on almost any UNIX platform. It has
 been tested on the following:
 <ul>
-<li> Solaris 2.4, 2.5, 2.5.1
-<li> SunOs 4.1.1, 4.1.3
+<li> Solaris 2.4, 2.5, 2.5.1, 2.6
 <li> Linux Red Hat 3, Red Hat 4, Slackware 3.0, Slackware 96
-<li> HP-UX 9, 10
+<li> Digital Unix (OSF/1)
+<li> HP-UX 10
 <li> AIX 4
 <li> IRIX
+<li> NetBSD 2.2.2
+<li> SunOs 4.1.1, 4.1.3
 <li> SCO UNIX
 <li> Ultrix
-<li> Digital Unix (OSF/1)
 </ul>
 
 After obtaining the Pike source you need to unpack it. To unpack Pike you
diff --git a/tutorial/types.h b/tutorial/types.h
index 3139be3547e681dd9b6bc2bf40d24b325ce328ef..dd58b4879d4c64a1d943f112801e401f0d874f47 100644
--- a/tutorial/types.h
+++ b/tutorial/types.h
@@ -1,4 +1,6 @@
 #define TAG string|object(Sgml.Tag)
 #define SGML array(TAG)
+#define TOC SGML
 #define INDEX_DATA mapping(string:array(string))
 #define INDEX mapping(string:mapping|array(string))
+#define WMML object(Wmml.Wmml)
diff --git a/tutorial/wmmltohtml2 b/tutorial/wmmltohtml2
index 40ff6041c7b5cf4f1c8f120b64e2f9ec154e9d72..5672ce387552dde90c0735ac2073070eb4c18d6f 100755
--- a/tutorial/wmmltohtml2
+++ b/tutorial/wmmltohtml2
@@ -17,16 +17,9 @@ int main(int argc, string *argv)
     werror("Verifying\n");
     Wmml.verify(data);
     werror("Concretizing\n");
-    data=Wmml.make_concrete_wmml(data);
-    werror("Verifying (again)\n");
-    Wmml.verify(data);
-    werror("Collecting TOC ");
-    SGML toc=Wmml.collect_toc(data);
-    werror("index ");
-    INDEX_DATA index=Wmml.collect_index(data);
-    // write(sprintf("%O\n",Wmml.group_index(Wmml.collect_index(data))));
+    WMML wmml=Wmml.make_concrete_wmml(data);
     werror("\nWriting output\n");
-    output()->output(argv[2],data,toc,index);
+    output()->output(argv[2],wmml);
     write("Ok\n");
     exit(0);
   };