From 8d8049be4641b66526db23a053119aee8096875e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Fredrik=20H=C3=BCbinette=20=28Hubbe=29?= <hubbe@hubbe.net>
Date: Tue, 6 Jul 1999 03:05:27 -0700
Subject: [PATCH] latex.pike now generates a (unfinished) table of contents and
 a half-working index

Rev: tutorial/.cvsignore:1.14
Rev: tutorial/Makefile:1.33
Rev: tutorial/Wmml.pmod:1.34
Rev: tutorial/html.pike:1.28
Rev: tutorial/latex.pike:1.4
---
 tutorial/.cvsignore |   1 +
 tutorial/.gitignore |   1 +
 tutorial/Makefile   |   1 +
 tutorial/Wmml.pmod  | 134 ++++++++++++++++++++++++++++++++++++-
 tutorial/html.pike  |  14 +++-
 tutorial/latex.pike | 158 +++++++++++++++++++++++++++++++++++++++++---
 6 files changed, 296 insertions(+), 13 deletions(-)

diff --git a/tutorial/.cvsignore b/tutorial/.cvsignore
index 585375328d..cb9c820fd1 100644
--- a/tutorial/.cvsignore
+++ b/tutorial/.cvsignore
@@ -19,5 +19,6 @@ tutorial.dvi
 tutorial.html
 tutorial.log
 tutorial.mif
+tutorial.pdf
 tutorial.tex
 tutorial_*.html
diff --git a/tutorial/.gitignore b/tutorial/.gitignore
index 1e8f91b7dd..cc2a927602 100644
--- a/tutorial/.gitignore
+++ b/tutorial/.gitignore
@@ -19,5 +19,6 @@
 /tutorial.html
 /tutorial.log
 /tutorial.mif
+/tutorial.pdf
 /tutorial.tex
 /tutorial_*.html
diff --git a/tutorial/Makefile b/tutorial/Makefile
index 4ab3ab413b..864e7d871d 100644
--- a/tutorial/Makefile
+++ b/tutorial/Makefile
@@ -57,6 +57,7 @@ tutorial.tex: .DUMMY $(SRCFILES)
 tutorial.dvi: tutorial.tex
 	-@rm tutorial.aux
 	latex tutorial.tex
+	latex tutorial.tex
 
 tutorial.ps: tutorial.dvi
 	dvips -Z tutorial.dvi
diff --git a/tutorial/Wmml.pmod b/tutorial/Wmml.pmod
index 5817495d68..26ff506e2f 100644
--- a/tutorial/Wmml.pmod
+++ b/tutorial/Wmml.pmod
@@ -209,6 +209,13 @@ INDEX_DATA collect_index(SGML data, void|INDEX_DATA index,void|mapping taken)
 	if(string real_name=data->params->name)
 	{
 	  string new_name=real_name;
+
+	  if(!strlen(new_name))
+	  {
+	    werror("Empty link name in <anchor> at %s\n",data->location());
+	    continue;
+	  }
+	      
 	  
 	  if(taken[new_name])
 	  {
@@ -226,6 +233,8 @@ INDEX_DATA collect_index(SGML data, void|INDEX_DATA index,void|mapping taken)
 	  }else{
 	    index[real_name]=({new_name});
 	  }
+	}else{
+	  werror("<anchor> without name near %s\n",data->location());
 	}
       }
       if(data->data)
@@ -278,8 +287,14 @@ INDEX group_index_by_character(INDEX i)
   foreach(indices(i),string key)
     {
       int c;
-      sscanf(lower_case(Html.unquote_param(key)),"%*[_ ]%c",c);
-      string char=upper_case(sprintf("%c",c));
+      string char;
+      if(sscanf(lower_case(Html.unquote_param(key)),"%*[_ ]%c",c)==2)
+      {
+	char=upper_case(sprintf("%c",c));
+      }else{
+	char="";
+      }
+
 //      werror(char +" : "+key+"\n");
       if(!m[char]) m[char]=([]);
       m[char][key]=i[key];
@@ -440,10 +455,20 @@ object(Tag) parse_pike_code(string x,
 // output generator.
 class Wmml
 {
+  // Header data
   SGML metadata;
+
+  // Table of contents
   TOC toc;
+
+  // Index
   INDEX_DATA index_data;
+
+  // Concrete WMML data
   SGML data;
+
+  // Link name to tag mapping
+  mapping(string:TAG) links;
 };
 
 // Enumerators are used to give numbers to chapters,
@@ -921,9 +946,114 @@ object(Wmml) make_concrete_wmml(SGML data)
   ret->index_data=collect_index(ret->data);
   ret->toc=toker->query();
   ret->metadata=metadata;
+  collect_links(ret->data,ret->links=([]));
+  ret->data=unlink_unknown_links(ret->data,ret->links);
+  
+  return ret;
+}
+
+// These routines are meant to create a mapping from a link name
+// to the corresponding TAG.
+
+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;
+}
+
+// must be called after Wmml has been made concrete
+void collect_links(SGML data, mapping known_links)
+{
+  foreach(data,TAG t)
+    {
+      if(objectp(t))
+      {
+	if(t->tag == "anchor")
+	{
+	  if(t->params->name)
+	  {
+	    known_links[t->params->name]=get_tag(t);
+	  }
+	}
+
+	if(t->data)
+	  collect_links(t->data,known_links);
+      }
+    }
+}
+
+// This finds nonworking links and makes them non-links,
+// this way the output controller doesn't have to worry
+// about broken links.
+SGML unlink_unknown_links(SGML data, mapping known_links)
+{
+  SGML ret=({});
+
+  foreach(data,TAG t)
+    {
+      if(objectp(t))
+      {
+	switch(t->tag)
+	{
+	  case "ref":
+	    if(!t->params->to)
+	    {
+	      werror("<ref> without to= at %s\n",t->location());
+	      continue;
+	    }
+	    if(!known_links[t->params->to])
+	    {
+	      werror("<ref to=> broken link at %s\n",t->location());
+	      continue;
+	    }
+	    break;
+
+	  case "link":
+	    if(!t->params->to)
+	    {
+	      werror("<ref> without to= at %s\n",t->location());
+	      ret+=unlink_unknown_links(t->data || ({}),known_links);
+	      continue;
+	    }
+	    if(!known_links[t->params->to])
+	    {
+	      werror("<ref to=> broken link at %s\n",t->location());
+	      ret+=unlink_unknown_links(t->data || ({}),known_links);
+	      continue;
+	    }
+	}
+	
+	if(t->data)
+	  t->data=unlink_unknown_links(t->data,known_links);
+      }
+      ret+=({t});
+    }
   return ret;
 }
 
+
 void save_image_cache();
 
 int gifnum;
diff --git a/tutorial/html.pike b/tutorial/html.pike
index 772c7c637e..d1ed084569 100644
--- a/tutorial/html.pike
+++ b/tutorial/html.pike
@@ -279,7 +279,7 @@ int count_index_lines(SGML z)
   return ret;
 }
 
-SGML index_to_wmml(INDEX data)
+SGML index_to_wmml_low(INDEX data)
 {
   SGML ret=({});
   foreach(srt(indices(data)-({0})),string key)
@@ -296,7 +296,19 @@ SGML index_to_wmml(INDEX data)
 	      });
       }
     }
+  return ret;
+}
 
+SGML index_to_wmml_onecol(INDEX data)
+{
+  SGML ret=index_to_wmml_low(data);
+  return ({ Sgml.Tag("dl",([]),0,ret) });
+}
+
+SGML index_to_wmml(INDEX data)
+{
+  SGML ret=index_to_wmml_low(data);
+  
 #if 1
   int total_lines=count_index_lines(ret);
 //  werror("\nTOTAL LINES: %d\n",total_lines);
diff --git a/tutorial/latex.pike b/tutorial/latex.pike
index b61069cf53..60fb8c6ae3 100644
--- a/tutorial/latex.pike
+++ b/tutorial/latex.pike
@@ -6,6 +6,8 @@ inherit Stdio.File : out;
 
 object html=.html();
 
+WMML global_data;
+
 string low_latex_quote(string text)
 {
   return replace( text,
@@ -35,6 +37,15 @@ string latex_quote(string text)
   return low_latex_quote( pre ? text : ((text/"\n") - ({""})) *"\n" );
 }
 
+string quote_label(string s)
+{
+  string ret="";
+  while(sscanf(s,"%[_a-zA-Z0-9.:]%c%s",string safe, int char, s)==3)
+    ret+=sprintf("%s-%02x",safe,char);
+  ret+=s;
+  return ret;
+}
+
 
 float weighted_strlen(string tag)
 {
@@ -65,6 +76,24 @@ float aproximate_length(SGML data)
   return len;
 }
 
+string mkref(string label)
+{
+  if(!global_data->links[label])
+  {
+    return "\\pageref{"+quote_label(label)+"}";
+  }
+  switch(global_data->links[label]->tag)
+  {
+    case "chapter":
+    case "section":
+    case "appendix":
+      return global_data->links[label]->tag+" \\ref{"+quote_label(label)+"}";
+
+    default:
+      return "\\pageref{"+quote_label(label)+"}";
+  }
+}
+
 string convert_table(TAG table)
 {
   SGML data=table->data;
@@ -134,6 +163,7 @@ string convert_table(TAG table)
 
   if(border) ret+="\\hline \\\\\n";
 
+  in_table++;
   foreach(data, TAG tag)
     {
       int c=0;
@@ -154,6 +184,7 @@ string convert_table(TAG table)
       ret+=row*" & "+"\\\\\n";
       if(border) ret+="\\hline\n";
     }
+  in_table--;
 
   ret+="\\end{longtable}\n";
 
@@ -180,9 +211,95 @@ string convert_image_to_latex(TAG tag)
   }
 }
 
+string *srt(string *x)
+{
+  string *y=allocate(sizeof(x));
+  for(int e=0;e<sizeof(y);e++)
+  {
+    y[e]=lower_case(x[e]);
+    sscanf(y[e],"%*[ ,./_]%s",y[e]);
+  }
+  sort(y,x);
+  return x;
+}
+
+string low_index_to_latex(INDEX data, string prefix, string indent)
+{
+//  werror("%O\n",data);
+  string ret="";
+  foreach(srt(indices(data)-({0})),string key)
+    {
+      ret+="\\item \\verb+"+indent+"+";
+      
+      if(data[key][0])
+      {
+	ret+=latex_quote(Html.unquote_param(key));
+	if(data[key][0][prefix+key])
+	{
+	  // FIXME: show all links
+	  ret+=", \\pageref{"+quote_label(data[key][0][prefix+key][0])+"}\n";
+	}
+	ret+="\n";
+
+	foreach(srt(indices(data[key][0])), string key2)
+	  {
+	    if(key2==prefix+key) continue;
+	    ret+="\\item \\verb+"+indent+"  +";
+	    ret+=latex_quote(Html.unquote_param(key2));
+	    ret+=", \\pageref{"+quote_label(data[key][0][key2][0])+"}\n";
+	}
+
+      }else{
+	ret+=latex_quote(Html.unquote_param(key))+"\n";
+      }
+	
+      if(sizeof(data[key]) > !!data[key][0])
+      {
+	ret+=low_index_to_latex(data[key],prefix+key+".",indent+"  ");
+      }
+    }
+
+  return ret;
+}
+
+
+// FIXME:
+// End chapter / appendix!!
+// Too long symbols, fix linebreaking or do not use
+// two-column mode...
+string index_to_latex(INDEX foo)
+{
+  string ret="";
+  ret+="\n\\twocolumn[\\begin{Huge}Index\\end{Huge}]\n\\begin{small}\n";
+  
+//  ret+="\\begin{Huge}Index\\end{Huge}\n\n";
+
+  INDEX data=Wmml.group_index(foo);
+  data=Wmml.group_index_by_character(data);
+
+  ret+="\\begin{list}{}{}\n";
+
+  foreach(srt(indices(data)-({0})),string key)
+    {
+      if(sizeof(data[key]) > !!data[key][0])
+      {
+	ret+="\n\\item \\begin{large}"+
+	  latex_quote(key)+
+	  "\\end{large}\n";
+
+	ret+=low_index_to_latex(data[key],"","  ");
+      }
+    }
+  ret+="\\end{list}\n";
+  ret+="\n\\end{small}\n\\onecolumn\n";
+  return ret;
+}
+
+
 int depth;
 int appendixes;
 int pre;
+int in_table;
 
 constant FLAG_TABLE=1;
 constant FLAG_LIST=2;
@@ -248,7 +365,7 @@ string convert_to_latex(SGML data, void|int flags)
 
 	  case "chapter":
 	    depth++;
-	    ret+="\\cleardoublepage \\section{"+
+	    ret+="\\chapter{"+
 	      latex_quote(tag->params->title)+"}\n"+
 	      convert_to_latex(tag->data);
 	    depth--;
@@ -261,7 +378,7 @@ string convert_to_latex(SGML data, void|int flags)
 	      appendixes=1;
 	    }
 	    depth++;
-	    ret+="\\cleardoublepage \\section{"+
+	    ret+="\\chapter{"+
 	      latex_quote(tag->params->title)+"}\n"+
 	      convert_to_latex(tag->data);
 	    depth--;
@@ -299,6 +416,17 @@ string convert_to_latex(SGML data, void|int flags)
 	    ret+=convert_to_latex(tag->data);
 	    break;
 
+	  case "table-of-contents":
+	    ret+="\\tableofcontents \\newpage\n";
+	    break;
+
+	  case "index":
+	  {
+	    ret+=index_to_latex(global_data->index_data);
+
+	    break;
+	  }
+
 	  case "pre":
 	    if(pre)
 	    {
@@ -315,7 +443,8 @@ string convert_to_latex(SGML data, void|int flags)
 
 	  case "encaps":
             // FIXME: Manual should not really use <encaps>
-	    ret+=convert_to_latex(tag->data);
+	    ret+="\\begin{scshape}"+convert_to_latex(tag->data)+
+	      "\\end{scshape}";
 	    break;
 
 	  case "bloackquote":
@@ -405,11 +534,16 @@ string convert_to_latex(SGML data, void|int flags)
 
 	  case "link":
 	    // FIXME
-//	    if(tag->params->to)
+	    // (la)tex doesn't like having too many links on one
+	    // page. We need to not do this for see-also links.
+	    // To do this we need to put hints in the concrete wmml
+//	    if(tag->params->to && !in_table)
 //	    {
 //	      ret+=
 //		convert_to_latex(tag->data)+
-//		"\\marginpar{See "+latex_quote(tag->params->to)+"}";
+//		"\\marginpar{See \\ref{"+
+//		quote_label(tag->params->to)+"} \\pageref{"+
+//		quote_label(tag->params->to)+"}.}";
 //	    }else{
 	      ret+=convert_to_latex(tag->data);
 //	    }
@@ -426,10 +560,9 @@ string convert_to_latex(SGML data, void|int flags)
 	    if(flags & FLAG_LIST)
 	      ret+="\\item ";
 	    else
-	      ; // FIXME, insert filled circle
+	      ret="$\\bullet$ ";
 	    break;
 
-
 	  case "ol":
 	    ret+="\\begin{enumerate} "+
 	      convert_to_latex(tag->data,FLAG_LIST)+
@@ -438,14 +571,15 @@ string convert_to_latex(SGML data, void|int flags)
 
 	  case "anchor":
 //          FIXME labels causes tex stack overflow!!
-//	    ret+="\\label{"+latex_quote(tag->params->name)+"}";
+	    ret+="\\label{"+quote_label(tag->params->name)+"}";
 	    ret+=convert_to_latex(tag->data);
 	    break;
 
 	  case "ref":
 	    // FIXME: must find out what type of object we are
 	    // referencing!!
-	    ret+="\\ref{"+tag->params->to+"}";
+	    
+	    ret+=mkref(tag->params->to);
 	    break;
 
 
@@ -502,6 +636,7 @@ string convert_to_latex(SGML data, void|int flags)
 
 void output(string base, WMML data)
 {
+  global_data=data;
   string x=convert_to_latex(data->data);
 
   x=replace(x,
@@ -529,6 +664,9 @@ void output(string base, WMML data)
     "\\end{document}\n";
   rm(base+".tex");
   Stdio.write_file(base+".tex",x);
+  array(string) lines=x/"\n";
+  array(int) linenum=indices("x"*sizeof(lines));
+  array(int) lenghts=sort(Array.map(lines,strlen),linenum,lines);
 
-  werror("Longest line is %d characters.\n",sort(Array.map(x/"\n",strlen))[-1]);
+  werror("Longest line is line %d (%d characters).\n",linenum[-1],lenghts[-1]);
 }
-- 
GitLab