diff --git a/tutorial/Makefile b/tutorial/Makefile
index 93eea8bab8cc55fedbcf1804526f4a245d5ed114..3e5c8f05a3603febe5958047bb2c3d3e382d4bfc 100644
--- a/tutorial/Makefile
+++ b/tutorial/Makefile
@@ -57,8 +57,8 @@ wmml.html: .DUMMY wmml.wmml
 manpages: .DUMMY $(SRCFILES)
 	$(pike) ./wmmltohtml2 tutorial.wmml manpages man/man
 
-mirar_tutorial.html: .DUMMY $(SRCFILES)
-	$(pike) ./wmmltohtml2 tutorial.wmml mirar_html mirar_tutorial
+mirar_tutorial: .DUMMY $(SRCFILES)
+	$(pike) ./wmmltohtml2 tutorial.wmml mirar_html tutorial
 
 the_image_module.html: Image.wmml the_image_module.wmml
 	$(pike) ./wmmltohtml2 the_image_module.wmml mirar_html the_image_module
@@ -80,6 +80,6 @@ export:
 mirar_www: Image.wmml the_image_module.html
 	ln -f `cat the_image_module.files` /home/mirar/www/image
 
-mirar_www_tutorial: mirar_tutorial.html
-	ln -f `cat mirar_tutorial.files` /home/mirar/www/pike_tutorial
+mirar_www_tutorial: mirar_tutorial
+	ln -f `cat tutorial.files` /home/mirar/www/pike_tutorial
 
diff --git a/tutorial/Sgml.pmod b/tutorial/Sgml.pmod
index d3c7db91cbfba0d2b549ed75d28b08bbcda6466f..7a47dc21c1720e08fdfae56b582a55f1fa14b669 100644
--- a/tutorial/Sgml.pmod
+++ b/tutorial/Sgml.pmod
@@ -106,7 +106,7 @@ SGML lex(string data, string file)
       if(sscanf(s,"%[^ \t\r\n>=]%s",string key,s) && strlen(key))
       {
 	key=lower_case(key);
-	if(s[0]=='=')
+	if(s!="" && s[0]=='=')
 	{
 	  string val;
 	  switch(s[1])
diff --git a/tutorial/Wmml.pmod b/tutorial/Wmml.pmod
index 36d9bfe802d05db327ad19ae8fc6bd42d4da4b40..ff1f6b313c95940d81a53c8172048d5900ead0ce 100644
--- a/tutorial/Wmml.pmod
+++ b/tutorial/Wmml.pmod
@@ -774,12 +774,16 @@ SGML low_make_concrete_wmml(SGML data)
         case "constant":
 	{
 	   array anchors=({}),fullnames=({});
+	   string last;
 
-	   foreach (replace(tag->params->name,">",">")/",",
-		    string name)
+	   foreach (replace(tag->params->name,
+			    ({"&gt;","&lt;"}),({">","<"}))/",",
+                    string name)
 	   {
 	      string fullname;
-	      if (name[0..strlen(classbase->query())-1]==
+	      if (name!="" && name[0]=='.')
+		 fullname=last+name[1..];
+	      else if (name[0..strlen(classbase->query())-1]==
 		  classbase->query() ||
 		  tag->params->fullpath)
 		 fullname=name;
@@ -787,7 +791,7 @@ SGML low_make_concrete_wmml(SGML data)
 	      {
 		 case "method":
 	         case "variable":
-		    fullname=classbase->query()+"->"+name;
+		    fullname=classbase->query()+"."+name; // -> ?
 		    break;
 		 case "function":
 	         case "constant":
@@ -795,7 +799,10 @@ SGML low_make_concrete_wmml(SGML data)
 		    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]);
 	   }
 	   array res=
 		    ({Tag("dl",([]),tag->pos,
@@ -812,14 +819,17 @@ SGML low_make_concrete_wmml(SGML data)
 				     :"")}))
 			  }) + tag->data ) });
 		   
+	   res=
+	      ({Tag(tag->tag,(["name":fullnames*", ",
+			       "title":tag->params->title]),tag->pos,
+		    low_make_concrete_wmml(res))});
+
 	   foreach (anchors,string anchor)
 	      res=({Tag("anchor",(["name":anchor]),
 			tag->pos,res)});
 
-	   ret+=
-	      ({Tag(tag->tag,(["name":fullnames*",",
-			       "title":tag->params->title]),tag->pos,
-		    low_make_concrete_wmml(res))});
+	   ret+=res;
+
 	   continue;
 	}
 
@@ -1083,7 +1093,7 @@ array execute_contents(Tag tag)
 
       array dat=data/"\n";
       
-      int i,mx=min(max(@column(cerrs,0))+4,sizeof(dat));
+      int i,mx=min(max(@column(cerrs,0))+5,sizeof(dat));
       for (i=max(0,min(@column(cerrs,0))-1);i<mx; i++)
 	 werror("%5d: %s\n",i+offs+1,dat[i]);
 
diff --git a/tutorial/html.pike b/tutorial/html.pike
index 04b497c5144207f1a92d0177399d86a75e6d75b4..9aa633964a2c3a67d233177f3ebf7204586da08d 100644
--- a/tutorial/html.pike
+++ b/tutorial/html.pike
@@ -44,9 +44,10 @@ TAG mkimgtag(string file, mapping params)
   if(params->align) p->align=params->align;
   if(params->alt) p->align=params->alt;
   add_file_to_export_list(file);
-  object o=Image.load(file);
-  p->xsize=(string)o->xsize();
-  p->ysize=(string)o->ysize();
+  object o;
+  if (catch { o=Image.load(file); }) return "<!-- error -->";
+  p->width=(string)o->xsize();
+  p->height=(string)o->ysize();
   return Sgml.Tag("img",p,0);
 }
 
@@ -505,7 +506,8 @@ SGML convert(SGML data)
 		  break;
 	       }
 	    }
-	    data->params->href=mklinkname(link_to_page[to])+"#"+to;
+	    data->params->href=mklinkname(link_to_page[to])+"#"+
+	       replace(to,({"`",">","<","?"}),({"BQ-","GT","LT","QM"}));
 	    break;
 	 }
 	
@@ -561,12 +563,18 @@ SGML convert(SGML data)
 	    else
 	       data->data=({"unknown"});
 	    data->tag="a";
-	    data->params->href=mklinkname(link_to_page[to])+"#"+to;
+	    data->params->href=mklinkname(link_to_page[to])+"#"+
+	       replace(to,({"`",">","<","?"}),({"BQ-","GT","LT","QM"}));
 	    break;
 	 }
 	
 	 case "anchor":
 	    data->tag="a";
+	    if (!data->params->name)
+	       werror("Warning: anchor without name (near "+data->location()+")\n");
+	    data->params->name=
+	       replace(data->params->name||"unnamed",
+		       ({"`",">","<","?"}),({"BQ-","GT","LT","QM"}));
 	    break;
 	
 	 case "ex_identifier":
diff --git a/tutorial/mirar_html.pike b/tutorial/mirar_html.pike
index db131279e19b256f9fd574b40cecc510a7ccf4ee..115baacf51090c4dc98f8234cffdfc92640bfc74 100644
--- a/tutorial/mirar_html.pike
+++ b/tutorial/mirar_html.pike
@@ -235,259 +235,29 @@ SGML convert(SGML data)
 	       });
 	    continue;
 
-	 case "link":
-	 {
-	    data->tag="a";
-	    string to=data->params->to;
-	    m_delete(data->params,"to");
-	    if(!link_to_page[to])
-	    {
-	       string s=(to/".")[-1];
-	       if (link_to_page[s]) 
-		  to=s;
-	       else
-	       {
-		  werror("Warning: Cannot find link "+to
-			 +" (near "+data->location()+")\n");
-		  data->tag="anchor";
-		  break;
-	       }
-	    }
-// 	    werror("--- %O --- %O\n",to,link_to_page[to]);
-	    data->params->href=mklinkname(link_to_page[to])+"#"+to;
-	    break;
-	 }
-	
 	 case "arguments":
-	    ret+=convert(({
-	       Sgml.Tag(
-		  "table",(["border":"1","cellspacing":"0"]),data->pos,
-		  ({Sgml.Tag(
-		     "tr",([]),data->pos,
-		     ({Sgml.Tag("td",(["align":"left"]),data->pos,
-				({Sgml.Tag("font",(["size":"-2"]),
-					   data->pos,({"argument(s)"}))})),
-		       Sgml.Tag("td",(["align":"left"]),data->pos,
-				({Sgml.Tag("font",(["size":"-2"]),
-					   data->pos,({"description"}))}))}))})+
-		  (data->data||({})))
-	    }));
+	    ret+=({ Sgml.Tag(
+	       "table",(["border":"0",
+			 "cellpadding":"0","cellspacing":"4"]),
+	       data->pos,
+	       convert(data->data||({}))) });
 	    continue;
 
 	 case "aargdesc":
-	    ret+=convert(({Sgml.Tag("tr",([]),data->pos,
-				    ({Sgml.Tag("td",(["valign":"top","align":"left"]))})+data->data)}));
+	    ret+=({Sgml.Tag(
+	       "tr",([]),data->pos,
+	       ({Sgml.Tag("td",(["valign":"top","align":"left"]))})+
+	       convert(data->data))});
 	    continue;
 	 case "adesc":
-	    ret+=convert(({Sgml.Tag("td",(["valign":"top","align":"left"]),data->pos,data->data)}));
-	    continue;
-	 case "aarg":
-	    ret+=convert(({Sgml.Tag("tt",([]),data->pos,data->data),
-			   Sgml.Tag("br")}));
-	    continue;
-
-	 case "exercises":
-	    ret+=convert(({Sgml.Tag("box",([]),data->pos,data->data)}));
-	    continue;
-	 case "exercise":
-	    ret+=convert(({Sgml.Tag("li",([]),data->pos,data->data)}));
-	    continue;
-
-	 case "data_description":
-	    ret+=data_description(data->params,data->pos,data->data,data);
-	    continue;
-
-	 case "ref":
-	 {
-	    string to=data->params->to;
-	    TAG t2=link_to_data[to];
-	    if(!t2)
-	    {
-	       werror("Warning: Cannot find ref "+to+" (near "+data->location()+")\n");
-	    }
-	    if(t2)
-	       data->data=({t2->tag+" "+t2->params->number+" \""+t2->params->title+"\""});
-	    else
-	       data->data=({"unknown"});
-	    data->tag="a";
-	    data->params->href=mklinkname(link_to_page[to])+"#"+to;
-	    break;
-	 }
-	
-	 case "anchor":
-	    data->tag="a";
-	    break;
-	
-	 case "ex_identifier":
-	 case "ex_commend":
-	    ret+=convert(data->data);
-	    continue;
-	 case "ex_string":
-	    ret+=convert(replace(data->data," "," "));
-	    continue;
-	
-	 case "example": data->tag="blockquote";break;
-	 case "ex_keyword": data->tag="b";break;
-	 case "ex_meta": data->tag="i";break;
-	 case "ex_br": data->tag="br"; break;
-
-	 case "ex_indent":
-	    ret+=({"    "});
-	    continue;
-
-	 case "table-of-contents":
-	 {
-	    SGML tmp=html_toc;
-	    if(data->params->target)
-	    {
-	       werror("(targeting)");
-	       tmp=Sgml.copy(tmp);
-	       add_target_to_links(tmp,data->params->target);
-	    }
-	    ret+=({
-	       Sgml.Tag("h1",([]),data->pos,
-			({
-			   data->title || "Table of contents",
-			}))
-	    
-	    })+convert(tmp);
-	    continue;
-	 }
-
-	 case "index":
-	    ret+=({
-	       Sgml.Tag("h1",([]),data->pos,
-			({
-			   data->title || "Index",
-			}))
-	    
-	    })+convert(html_index);
-	    continue;
-
-	 case "preface":
-	 case "introduction":
-	    ret+=
-	       ({
-		  Sgml.Tag("h1",([]),data->pos,
-			   ({
-			      data->params->title,
-			   })),
-		  "\n",
-	       })+
-	       convert(data->data);
-	       continue;
-
-	 case "chapter":
-	    ret+=
-	       ({
-		  Sgml.Tag("h1",([]),data->pos,
-			   ({
-			      "Chapter ",
-			      data->params->number,
-			      ", ",
-			      data->params->title,
-			   })),
-		  "\n",
-	       })+
-	       convert(data->data);
-	       continue;
-
-	 case "appendix":
-	    ret+=({
-	       Sgml.Tag("h1",([]),data->pos,
-			({
-			   "Appendix ",
-			   data->params->number,
-			   ", ",
-			   data->params->title||error("Appendix without title"),
-			})),
-	       "\n"
-	    })+
-	       convert(data->data)
-		  ;
-	       continue;
-
-	 case "section":
-	 {
-	    string *tmp=data->params->number/".";
-	    int level=sizeof(tmp);
-	    switch(tmp[0])
-	    {
-	       case "introduction":
-	       case "preface":
-		  ret+=({
-		     Sgml.Tag("h"+level,([]),data->pos,
-			      ({
-				 data->params->title,
-			      })),
-		     "\n"
-		  })+
-		     convert(data->data)
-			;
-		     continue;
-
-	       default:
-		  ret+=({
-		     Sgml.Tag("h"+level,([]),data->pos,
-			      ({
-				 data->params->number,
-				 " ",
-				 data->params->title,
-			      })),
-		     "\n"
-		  })+
-		     convert(data->data)
-			;
-		     continue;
-	    }
-	 }
-
-	 case "encaps":
-	 {
-	    SGML t=({});
-
-	    foreach(data->data[0]/" "-({""}),string tmp)
-	    {
-	       t+=({
-		  Sgml.Tag("font",(["size":"+1"]),data->pos,({tmp[0..0]})),
-		  Sgml.Tag("font",(["size":"-1"]),data->pos,({tmp[1..]})),
-		  " "
-	       });
-	    }
-	
-	    ret+=({ Sgml.Tag("b",([]),data->pos,t) });
-	    continue;
-	 }
-
-	 case "img":
-	    add_file_to_export_list(data->params->src);
-	    break;
-
-	 case "illustration":
-	    ret+=({ mkimgtag(Wmml.illustration_to_gif(data,75.0),data->params) });
+	    ret+=({"   ",Sgml.Tag("/td",([])),
+		   Sgml.Tag("td",(["valign":"top","align":"left"]),
+			    data->pos,convert(data->data))});
 	    continue;
-
-	 case "image":
-	    ret+=({ mkimgtag(Wmml.image_to_gif(data,75.0),data->params) });
-	    continue;
-
-	 case "box":
-	    ret+=({
-	       Sgml.Tag("table",
-			(["cellpadding":"10",
-			  "width":"100%",
-			  "border":"1",
-			  "cellspacing":"0"]),data->pos,
-			({
-			   "\n",
-			   Sgml.Tag("tr",([]),data->pos,
-				    ({
-				       Sgml.Tag("td",([]),data->pos,
-						convert(data->data))
-				    }))
-			})),
-	       "\n",
-	    });
+	 case "aarg": 
+	    ret+=({Sgml.Tag("tt",([]),data->pos,
+			    convert(data->data)),
+		   Sgml.Tag("br")});
 	    continue;
 
 	 case "method":
@@ -535,8 +305,7 @@ SGML convert(SGML data)
 		  )});
 	    continue;
       }
-      data->data=convert(data->data);
-      ret+=({data});
+      ret+=::convert(({data}));
     }
   }
   return ret;