Index: trunk/hepdata-webapp/src/main/java/cedar/hepdata/webapp/components/DatasetAsHtml.java
===================================================================
--- trunk/hepdata-webapp/src/main/java/cedar/hepdata/webapp/components/DatasetAsHtml.java	(revision 1828)
+++ trunk/hepdata-webapp/src/main/java/cedar/hepdata/webapp/components/DatasetAsHtml.java	(revision 1829)
@@ -1,805 +1,805 @@
 package cedar.hepdata.webapp.components;
 
 import org.apache.tapestry5.MarkupWriter;
 import org.apache.tapestry5.annotations.BeginRender;
 import org.apache.tapestry5.annotations.Parameter;
 import org.apache.tapestry5.annotations.Path;
 import org.apache.tapestry5.ioc.annotations.*;
 import org.apache.tapestry5.services.*;
 import org.apache.tapestry5.Asset;
 
 import cedar.hepdata.model.*;
 import cedar.hepdata.util.*;
 import cedar.hepdata.webapp.pages.*;
 
 import com.Ostermiller.util.SignificantFigures;
 
 import java.text.*;
 import java.util.*;
 import java.io.*;
 import java.io.File;
 
 
 public class DatasetAsHtml {
 
     @Inject
 	private RequestGlobals _reqGlobals;
 
     @Inject
 	@Path("context:/button_expand.png")
 	private Asset button_expand;
 
     @Inject
 	@Path("context:/button_hide.png")
 	private Asset button_hide;
 
     @Parameter
 	private String _format;
     public String getFormat() { return _format; }
     public void getFormat(String f) { _format = f; }
 
 
 
     @BeginRender
 	void renderMessage(MarkupWriter writer) {
 
         String dsid = "datacell"+_dataset.getId().toString();
         // Output the table comment(CT) omitting the location(TFP)
 	//     writer.element("p");
         writer.attributes("class", "datasetcomments");
         boolean verbatim = false;
         boolean plotit = true;
         for (String comment : _dataset.getComments()) {
             if(!comment.startsWith("Location")){
                 if(comment.startsWith("VERBATIM")){verbatim = true;}
                 int ls=comment.length();
                 while (ls>0){
                     int iend = ls;
                     int ihash = comment.indexOf("#");
                     if(ihash>0) { iend = ihash; }
 		    //                    writer.element("br"); writer.end();
 		    //                    writer.write(comment.substring(0,iend));
                     if(iend<ls){ 
                         comment=comment.substring(ihash+1);
                         ls=comment.length();
                     } else {
                         ls=0;
                     }
                 }
             }
         }
 
 	// now try to deal with additional dataset errors...
         for (DatasetError de : _dataset.getErrors()){
             writer.write("Additional systematic error: ");
             if(de.getPlus() != 0.0 || de.getPlus() != 0.0) {
                 if(de.getPlus().equals(de.getMinus())){
                     writer.writeRaw("&plusmn;");
                     writer.write(" " + de.getPlus());
                 } else{
 		    writer.write("+" + de.getPlus() + ",-" + de.getMinus() + " ");
                 }
                 writer.write(de.getNormType().toSymbol()+ " ");
             }
             writer.write("(" +de.getComment() + ")");
             writer.element("br");writer.end();
         }
         String lasterror = "";
         int ycount = 0;
         for (YAxis y : _dataset.getYAxes()){
             ycount += 1;
             for (AxisError ye : y.getErrors()){
                 String newerror = "e" + ye.getPlus() + ye.getMinus() + ye.getNormType() + ye.getComment();
                 if(!newerror.equals(lasterror)){
                     writer.element("br");writer.end();
                     writer.write("Additional systematic error(" + ycount + "): ");
                     if(ye.getPlus() != 0.0 || ye.getPlus() != 0.0) {
                         if(ye.getPlus().equals(ye.getMinus())){
                             writer.writeRaw("&plusmn;");
                             writer.write(" " + ye.getPlus());
                         } else{
                             writer.write("+" + ye.getPlus() + "-" + ye.getMinus() + " ");
                         }
                         writer.write(ye.getNormType().toSymbol()+ " ");
                     }
                     writer.write("(" +ye.getComment() + ")");
                 }
                 lasterror = newerror;
             }
         }
        
 	//        writer.end(); //p 
 
 	// This next sections adds any extra information to the specific table.
 	// Not ideal because the relative table Id could change but I see no better was.
 	// Requires two files:   description.n and link.n in the specific resource direcotry
         String location=""; 
         for (String comment : _dataset.getComments()){
 	    if(comment.startsWith("Location:")) {
 		location = comment.substring(10).replaceAll(" ","_");
 	    }
         }
         
         Long paperid = _dataset.getPaper().getSpiresId();
         if(paperid==null){
             paperid = _dataset.getPaper().getRedId();
             if(paperid==null){
                 paperid = _dataset.getPaper().getInspireId();
             }
         }
         String descname="/home/hepdata/resource/"+paperid+"/description."+location;
         String linkname="/home/hepdata/resource/"+paperid+"/link."+location;
         File descfile = new File(descname);
         if(descfile.exists()) {
 	    try{
 		BufferedReader indesc=new BufferedReader(new FileReader(descname));
 		BufferedReader inlink=new BufferedReader(new FileReader(linkname));
 		String desc = indesc.readLine();
 		String link = inlink.readLine();
 		writer.write(desc);
 		writer.element("a");
 		writer.attributes("href","/resource/"+paperid+"/"+link);
 		writer.write(" table:"+location);
 		writer.end();
 	    } catch (IOException e){}
         }
 
         // Determine the number of axes and points in the dataset
         final int nx = _dataset.getXAxes().size(); // number of xaxes in the dataset
         final int ny = _dataset.getYAxes().size();  // number of yaxes in the dataset
         int npoints = _dataset.getNumPoints();
         int binIdMax = _dataset.getMaxPointId();
 
         // Determine the number of axis comments and properties for this dataset
         int ncomm = 0;
         int nprop = 0;
         if (_dataset.getYAxes().size() > 0) {
             for(YAxis y : _dataset.getYAxes()){
                 if(y.getComments().size() > ncomm) {ncomm = y.getComments().size();}
                 if(y.getProperties().size() > nprop) {nprop = y.getProperties().size();}
             } 
         }
         // Begin the actual data table...
         writer.element("table");
         writer.attributes("class", "dataset");
 
 	// y-axis comments (i.e. non-numerical properties
 	// new version has these added in with the properties - below
         int nmatch = 0;
 
         // Next the numerical properties new version
 
         String[][] store = new String[ny][nprop+ncomm];
         int numy = -1;
         for(YAxis y : _dataset.getYAxes()) {
             numy++;
             int j=-1;
             List <String> storelist = new ArrayList();
             // first add the comment elements (strings)
             for (String comment : y.getComments()){
                 if(!comment.startsWith("RE") && comment.indexOf(" IN ") > 0 && comment.indexOf(" : ") > 0){
                     int len = comment.length();
                     int ip1 = comment.indexOf(" IN ");
                     int ip2 = comment.indexOf(" : ");
                     if(ip2 > ip1) { 
                         String comment2 = comment.substring(0,ip1);
                         comment2 += comment.substring(ip2,len);
                         comment2 += comment.substring(ip1+3,ip2).replace("EV","eV");
                         comment = comment2;
                     }
                     else{
                         String comment2 = comment.substring(0,ip2);
                         comment2 += comment.substring(ip1,len);
                         comment2 += comment.substring(ip2+3,ip1).replace("EV","eV");
                         comment = comment2;
                     }
                 }
                 if(comment.startsWith(". :")){
 		    comment = comment.replace(". :","zzzz :");
 		}
                 if(!comment.startsWith("Axis error")){ 
 		    storelist.add(comment);
                 } else{
 		    comment=comment.replaceFirst("Axis","Axis("+y.getId().toString()+")");
 		    writer.write(comment);
 		    writer.element("br");
 		    writer.end();
                 }
             }
             for (Property property : y.getProperties()) {
                 j++;
                 String tempstr = property.getName().toString();
 		tempstr = tempstr.concat(" : ");
 		if (property.getFocus() != null){
 		    tempstr = tempstr.concat(property.getFocus().toString());
 		}
 		if (property.getLowValue() != null && property.getHighValue() != null &&
 		    property.getLowValue().equals(property.getHighValue())) {
 		    tempstr = tempstr.concat(property.getLowValue().toString());
 		} else {
 		    if(property.getFocus() != null) { tempstr = tempstr.concat(" ("); }
 		    tempstr = tempstr.concat(property.getLowValue().toString());
 		    tempstr = tempstr.concat("-");
 		    tempstr = tempstr.concat(property.getHighValue().toString());
 		    if(property.getFocus() != null) { tempstr = tempstr.concat(")"); }
 		}
 		if (property.getUnit().toString().equals("") || !property.getUnit().isDimensionless()) {
 		    tempstr = tempstr.concat(" ");
 		    tempstr = tempstr.concat(property.getUnit().toString());
 		}
 		if(tempstr.startsWith(". :")){
 		    tempstr = tempstr.substring(3);
 		}
 		storelist.add(tempstr);
             }
             Collections.sort(storelist);
             int ij=-1;
             for (int i=0; i<storelist.size(); i++){
                 if(i>0 && storelist.get(i).equals(storelist.get(i-1))){ nprop -= 1;}
                 else{
                     ij += 1;
                     store[numy][ij] = storelist.get(i).replaceFirst("sqrts","SQRT(S)").replaceFirst("zzzz :","");
                 } 
             }
         }
         for (int i=0; i<nprop+ncomm; i++){
             if(store[0][i] != null){
                 writer.element("tr");
                 writer.element("td");
                 writer.attributes("colspan", nx);
                 if(i==nprop+ncomm-1) { writer.attributes("class","xqualifier_last qualifier_class");}
                 else { writer.attributes("class","xqualifier qualifier_class"); }
                 if(store[0][i].indexOf(" : ")>-1){ 
                     writer.write(store[0][i].substring(0,store[0][i].indexOf(" : ")));
                 }
                 else{
 		    //      writer.write(store[0][i]);
                 }
 		//                if(store[0][i].startsWith("RE")){
 		//                    writer.element("a");
 		//                    writer.attributes("href","/h3test/ReactionHelp");
 		//                    writer.attributes("onClick","return popitup(this)");
 		//                    writer.attributes("title","click for more help on this reaction");
 		//                    writer.writeRaw("?=>");
 		//                    writer.end();
 		//                }
 		//                else{
 		//                    writer.writeRaw("&nbsp;");
 		//                }
                 writer.end();
 
 		// this is the actual output
 		// first check is same across row
                 Boolean same = true;
                 for (int nmy=0; nmy<ny-1; nmy++){ 
                   
                     if(store[nmy][i] != null && store[nmy+1][i] != null){                 
                         if(!store[nmy][i].equals(store[nmy+1][i])){ 
                             same = false; 
                         } 
                     } else{
                         same = false;
                     }  
                 }
                 
                 if(same) {
                     writer.element("th");
                     writer.attributes("colspan",ny);
                     if(i<nprop+ncomm-1) { writer.attributes("class","multiple qualifier_class"); }
                     else { writer.attributes("class","multiple_last qualifier_class"); }
                     if(store[0][i].indexOf(" : ")>-1) { 
                         writer.write(store[0][i].substring(store[0][i].indexOf(" : ")+2));
                     }
                     else{
                         writer.write(store[0][i]);
                     }
                     writer.end();
                 } else {
                     int ii=0;
                     if(store[0][i].indexOf(":")>0) { ii = store[0][i].indexOf(":"); }
                     for (int nmy=0; nmy<ny; nmy++){
                         writer.element("th");
                         if(i<nprop+ncomm-1) { writer.attributes("class","multiple qualifier_class"); } 
                         else { writer.attributes("class","multiple_last qualifier_class"); } 
                         if(store[nmy][i] != null) {
                             if(nmy>0){ writer.write( store[nmy][i].substring(ii+1)); }
 			    //     if(nmy<0){ writer.write( store[nmy][i].substring(ii+1)); }
                             else { 
                                 if(store[nmy][i].indexOf(" : ")>-1) { 
                                     writer.write( store[nmy][i].substring(store[nmy][i].indexOf(" : ")+2)); 
                                 }
                                 else{
                                     writer.write( store[nmy][i]); 
                                 }
                             }
                         }
                         writer.end();
                     }
                 }
                 writer.end();  //tr    
             }
         }
         // Headers
         writer.element("tr");
         writer.attributes("class", "xyheaders");
 
 	// X headers
         for (XAxis x : _dataset.getXAxes()) {
             writer.element("th");
             writer.attributes("class", "xheader qualifier_class");
             writer.write(x.getHeader());
             writer.end(); //th
         }
 
         // Y headers (trying to merge if possible)
         String yhead = "";
         if (_dataset.getYAxes().size() > 0) {
             yhead = _dataset.getYAxis(1).getHeader();
         }
         nmatch = 0;
         for (YAxis y : _dataset.getYAxes()){
             if ( y.getHeader().equals(yhead) ) nmatch += 1;
         }
         if (nmatch == ny) {
             writer.element("th");
             writer.attributes("class", "yheader observable_class");
             writer.attributes("colspan", ny);
             writer.write(yhead);
             writer.end(); //th
         } else {
             for (YAxis y : _dataset.getYAxes()) {
                 writer.element("th");
                 writer.attributes("class", "yheader observable_class");
                 writer.write(y.getHeader());
                 writer.end(); //th
             }
         }
         writer.end(); //tr
 
 	///////////////////////////////////////////////////////////////////////////////////////////
         if(_dataset.getNumPoints() == 0){
             writer.element("th");
             writer.attributes("colspan",ny+nx);
             writer.attributes("align", "center");
             writer.write("No data is encoded for this table");
             writer.end();
         }
 	//       writer.element("tr");
 	//         writer.element("td");
 	//           writer.attributes("colspan",nx+ny);
 	//         writer.end();
 	//           writer.element("img");
 	//           writer.attributes("src",button_hide.toClientURL());
 	//           String hide = button_hide.toClientURL();
 	//           String expand = button_expand.toClientURL();
 	//           writer.attributes("onclick","ExpandClicked(this,'"+expand+"','"+hide+"');");
 	//         writer.end();
 	//       writer.end();
 
 	//        if (getFormat().equals("full") && _dataset.getNumPoints() != 0) {
         if ( _dataset.getNumPoints() != 0) {
 
             // Finally the numbers themselves
             int sumzero = 0;
             int allzero = 0;
             for (int ip = 1 ; ip <= npoints; ip++) {
                 writer.element("tr");
 
                 // First the xaxes
                 for (int ix = 1 ; ix <= nx; ix++) {
                     XAxis x = _dataset.getXAxis(ix);
 
                     // Work out x-axis formatting
                     /// @todo Do this formatting stuff properly with SignificantFigures as for y-values
                     int lwidth = 0;
                     int hwidth = 0;
                     int fwidth = 0;
                     // Format as "<focus> (bin: <low>--<high>)" if showmean is true ==
                     // at least one bin has a focus which significantly differs from the mean
                     // ..force it to be true so that we always output the mean
                     boolean asymmfocus = false;
                     boolean haswidth = false;
                     for (Bin b : x.getBins()) {
                         if(b.getDescription() !=null && b.getFocus()==null) {  plotit=false; }
                         if (b.getLowValue() != null && b.getHighValue() != null && b.getFocus() != null) {
                             double diff = b.getFocus() - (b.getLowValue() + b.getHighValue()) / 2.0;
                             if (Math.abs(diff/b.getFocus()) > 1E-6) {
                                 asymmfocus = true;
                             }
                         }
                         if (b.getLowValue() != null && b.getHighValue() != null){
                             double diff = b.getHighValue() - b.getLowValue();
                             double mean = (b.getHighValue() + b.getLowValue())/2.0;
                             if(Math.abs(diff/mean) > 1E-6){
                                 haswidth = true;
                             }
                         }
                         if (b.getLowValue() != null && b.getLowValue().toString().length() > lwidth) {
                             lwidth = b.getLowValue().toString().length();
                         }
                         if (b.getHighValue() != null && b.getHighValue().toString().length() > hwidth) {
                             hwidth = b.getHighValue().toString().length();
                         }
                         if (b.getFocus() != null && b.getFocus().toString().length() > fwidth) {
                             fwidth = b.getFocus().toString().length();
                         }
                     }
                     Double f = null;
                     Double high = null;
                     Double low = null;
                     Bin b = x.getBin(ip);
                     writer.element("td");
                     if(ip == npoints) {  writer.attributes("class", "xval_last"); }
                     else {  writer.attributes("class", "xval"); }
                     if (b != null) {
                         if (b.getDescription() == null){
                             if (b.getRelation() == Relation.EQUALS) {
                                 low = b.getLowValue();
                                 high = b.getHighValue();
                                 f = b.getFocus();
                                 int lsd = 0;
                                 int msd = 0;                             
                                 if(f != null) {  
                                     SignificantFigures valx = new SignificantFigures(f);
                                     lsd = valx.getLSD();
                                     msd = valx.getMSD();
-                                    if(msd == 0) msd = 1;
+                                    if(msd <= 0) msd = 1;
                                     if(f.toString().indexOf("9999999") > 0) {
                                         int pos1 =  f.toString().indexOf("9999999");
                                         int pos2 =  f.toString().indexOf(".");
                                         lsd = pos2-pos1+1;
                                     }
                                     else if(f.toString().indexOf("0000000") > 0) {
                                         int pos1 =  f.toString().indexOf("0000000");
                                         int pos2 =  f.toString().indexOf(".");
                                         lsd = pos2-pos1+1;
                                     }
                                     if(b.getFocusLength() != null){
                                         lsd = -b.getFocusLength();
                                     }  
                                 }
                                 String f_val = Formats.forms(f,fwidth, msd,-lsd);
                                 if(lsd == -1 && f_val.endsWith(".0") &&  b.getFocusLength() == null){ f_val = f_val.substring(0,f_val.length()-2); }
 
                                 if (low != null && high != null) {
                                     SignificantFigures vall = new SignificantFigures(low);
                                     lsd = vall.getLSD();
                                     msd = vall.getMSD();
-                                    if(msd == 0) msd = 1;
+                                    if(msd <= 0) msd = 1;
                                     if(low.toString().indexOf("9999999") > 0) {
                                         int pos1 =  low.toString().indexOf("9999999");
                                         int pos2 =  low.toString().indexOf(".");
                                         lsd = pos2-pos1+1;
                                     }
                                     else if(low.toString().indexOf("0000000") > 0) {
                                         int pos1 =  low.toString().indexOf("0000000");
                                         int pos2 =  low.toString().indexOf(".");
                                         lsd = pos2-pos1+1;
                                     }    
                                     if(b.getLowValueLength() != null){
                                         lsd = -b.getLowValueLength();
                                     }  
                                     String f_low = Formats.forms(low,lwidth,msd,-lsd);
 
                                     SignificantFigures valh = new SignificantFigures(high);
                                     lsd = valh.getLSD();
                                     msd = valh.getMSD();
-                                    if(msd == 0) msd = 1;
+                                    if(msd <= 0) msd = 1;
                                     if(high.toString().indexOf("9999999") > 0) {
                                         int pos1 =  high.toString().indexOf("9999999");
                                         int pos2 =  high.toString().indexOf(".");
                                         lsd = pos2-pos1+1;
                                     }
                                     else if(high.toString().indexOf("0000000") > 0) {
                                         int pos1 =  high.toString().indexOf("0000000");
                                         int pos2 =  high.toString().indexOf(".");
                                         lsd = pos2-pos1+1;
                                     }    
                                     if(b.getHighValueLength() != null){
                                         lsd = -b.getHighValueLength();
                                     }  
                                     String f_high = Formats.forms(high,hwidth,msd,-lsd);
 
 
                                     Double width = high - low;
                                     if (f != null && asymmfocus && haswidth) {
                                         writer.writeRaw(f_val);
                                         writer.writeRaw("&nbsp;(bin:&nbsp;");
                                         writer.writeRaw(f_low + "&nbsp;&ndash;&nbsp;" + f_high);
                                         writer.writeRaw(")");
                                     } else if (f==0.0 && haswidth==false || (f != null && Math.abs(width/f) < 1E-6)) {
                                         writer.write(f_val);
                                     } else {
                                         writer.writeRaw(f_low + "&nbsp;&ndash;&nbsp;" + f_high);
                                     }
                                 } else {
                                     writer.write(f_val);
                                 }
                             } else {
                                 writer.write(b.getRelation().toString());
                                 if (b.getLowValue() != null) {
                                     writer.write(b.getLowValue().toString());
                                 } else if (b.getHighValue() != null) {
                                     writer.write(b.getHighValue().toString());
                                 }
                             }
                         } else {
                             writer.write(b.getDescription());
                         }
                     }
                     writer.end(); //td
                 }
 
 
                 // Now the y-axes
                 for (int iy = 1; iy <= ny; ++iy) {
                     YAxis y = _dataset.getYAxis(iy);
                     Point pt2 = y.getPoint(ip);
                     writer.element("td");
                     if(ip == npoints) { writer.attributes("class", "yval_last"); }
                     else {  writer.attributes("class", "yval"); }
                     try {
                         /// DON'T MODIFY ANY OF THIS AT THE MOMENT: I'M MOVING THE FORMATTING TO AN EXTERNAL CLASS!
                         if (pt2.getRelation() != Relation.EQUALS) {
                             writer.write(pt2.getRelation().toString());
                         }
 
 			if (pt2.getDescription() != null) {
 			    plotit=false;
 			    writer.write(pt2.getDescription().toString());
 			}
 			else {
 
 			    SignificantFigures val = new SignificantFigures(pt2.getValue());
 			    int lsd = val.getLSD();
 			    allzero += 1;
 			    if (pt2.getValue().toString().endsWith(".0")) sumzero += 1; 
 			    if (pt2.getValue().toString().endsWith("0") || pt2.getValue().toString().indexOf("0E") > 0) {
 				lsd += 1;
 			    }
 			    
 			    if(pt2.getValueLength() != null && pt2.getValueLength() > 0) {
 				lsd = -pt2.getValueLength();
 			    } 
 			    else{                        
 				if (pt2.getRelation() == Relation.EQUALS) {
 				    for (PointError e : pt2.getErrors()) {
 					int lsd1 = 0;
 					int lsd2 = 0;
 					if (e.getNormType() != ErrorNorm.PCT) {
 					    SignificantFigures vale1 = new SignificantFigures(e.getPlus());
 					    lsd1 =  vale1.getLSD();
 					    if(!e.getPlus().toString().endsWith("0") && e.getPlus().toString().indexOf("0E") <= 0){
 						//                                    if(e.getPlus().toString().indexOf("0E") > 0){ lsd1 -= 1; }
 						lsd = Math.min(lsd, lsd1); 
 					    }
 					    SignificantFigures vale2 = new SignificantFigures(e.getMinus());
 					    lsd2 =  vale2.getLSD();
 					    if(!e.getMinus().toString().endsWith("0") && e.getMinus().toString().indexOf("0E") <= 0){
 						//                                    if(e.getMinus().toString().indexOf("0E") > 0){ lsd2 -= 1; }
 						lsd = Math.min(lsd, lsd2); 
 					    }
 					}
 				    }
 				}
 			    }
 			    int msd = val.getMSD();
 			    if (msd <= 0) msd = 1;
 			    //             `           if(allzero == sumzero) lsd = 0;
 			    if (verbatim) { writer.write(pt2.getValue().toString().replaceAll("E","e")); }
 			    else{ writer.write(Formats.forms(pt2.getValue(),msd, -lsd)); }
 			    
 			    if (pt2.getRelation() == Relation.EQUALS) {
 				for (PointError e : pt2.getErrors()) {
 				    String stype = e.getSourceType().toShortString();
 				    SignificantFigures vale = null;
 				    if (e.getPlusLength() != null) { lsd = -e.getPlusLength(); }
 				    if (e.isSymmetric() || e.hasZeroSize()) {
 					vale = new SignificantFigures(e.getPlus());
 					writer.writeRaw(" &plusmn;&nbsp;"); // chosen to allow breaks *before* the +- sign only
 					if (e.getNormType() == ErrorNorm.PCT) { lsd = vale.getLSD(); }
 					msd = vale.getMSD();
 					if (msd <= 0) msd = 1;
 					if (verbatim) { writer.write(e.getPlus().toString().replaceAll("E","e")); }
 					else {writer.write(Formats.forms(e.getPlus(), msd, -lsd)); }
 					writer.write(e.getNormType().toSymbol());
 				    } else if (e.isSymmetricReversed()) {
 					vale = new SignificantFigures(e.getPlus());
 					writer.writeRaw(" &#8723;&nbsp;"); // chosen to allow breaks *before* the +- sign only
 					if (e.getNormType() == ErrorNorm.PCT) { lsd = vale.getLSD(); }
 					msd = vale.getMSD();
 					if (msd <= 0) msd = 1;
 					if (verbatim) { writer.write(e.getMinus().toString().replaceAll("E","e")); }
 					writer.write(Formats.forms(e.getMinus(), msd, -lsd));
 					writer.write(e.getNormType().toSymbol());
 				    } else {
 					vale = new SignificantFigures(e.getPlus());
 					if (e.getPlus()<0.0) { writer.write(""); }
 					else { writer.write(" +"); }
 					if (e.getNormType() == ErrorNorm.PCT) { lsd = vale.getLSD(); }
 					msd = vale.getMSD();
 					if (msd <= 0) msd = 1;
 					if (verbatim) { writer.write(e.getPlus().toString().replaceAll("E","e")); }
 					else { writer.write(Formats.forms(e.getPlus(), msd, -lsd)); }
 					writer.write(e.getNormType().toSymbol());
 					vale = new SignificantFigures(e.getMinus());
 					if (e.getMinus()<0.0) { writer.write(","); }
 					else if (e.getMinus()>0.0) { writer.write(",+"); }
 					else { writer.write(",-"); }
 					if (e.getNormType() == ErrorNorm.PCT) { lsd = vale.getLSD(); }
 					msd = vale.getMSD();
 					if (msd <= 0) msd = 1;
 					if (verbatim) { writer.write(e.getMinus().toString().replaceAll("E","e")); }
 					else{ writer.write(Formats.forms(e.getMinus(), msd, -lsd)); }
 					writer.write(e.getNormType().toSymbol());
 				    }
 				    if(!stype.equals("?")) { writer.writeRaw("&nbsp;(" + stype);
 					if(!e.getComment().equals("")) { 
 					    writer.write("," + e.getComment()); 
 					}
 					writer.writeRaw(") ");
 				    }
 				}
 			    }
 			    for (PointError e : pt2.getErrors()){
 				if(!e.getComment().equals("")&&!e.getSourceType().toShortString().equals("sys")) { writer.write(" (" + e.getComment() + ")"); }
 			    }
 			}
 		    }
                     catch (Exception e) {
                         writer.writeRaw("&ndash;");
                     }
                     writer.end(); //td
                 }
 
                 writer.end(); //tr
             }
 
 
             // Alternative formats (link from table list)
             /// @todo Move to component template or separate component
             if(plotit==true){
 		writer.element("tr");
 		writer.attributes("class", "altformats");
 		for (int ix = 1; ix <= nx; ix++) {
 		    writer.element("td");
 		    writer.writeRaw("&nbsp;");
 		    writer.end(); //td
 		}
 
 		String baseurl = _reqGlobals.getRequest().getContextPath();
 		String urlid = "";
 		if(_dataset.getPaper().getInspireId() != null) { urlid = "/ins"+_dataset.getPaper().getInspireId(); }
 		else if(_dataset.getPaper().getSpiresId() != null) { urlid = "/irn"+_dataset.getPaper().getSpiresId(); }
 		else if(_dataset.getPaper().getCdsId() != null) { urlid = "/cds"+_dataset.getPaper().getCdsId(); }
 		else if(_dataset.getPaper().getRedId() != null) { urlid = "/red"+_dataset.getPaper().getRedId() ;}
 		else { urlid = "/p"+_dataset.getPaper().getId(); }
 		String urlparts = ""
 		    + urlid 
 		    + "/d" + _dataset.getId();
 		for (int iy = 1; iy <= ny; iy++) {
 		    writer.element("td");
 
 		    // // Numbers link
 		    // writer.element("a");
 		    // writer.attributes("href", baseurl + "/view:plain?" + urlparts + "&x=1&y=" + iy);
 		    // writer.attributes("title", "View the contents of this axis as plain text");
 		    // writer.write("Numbers");
 		    // writer.end();
 
 		    // writer.element("br"); writer.end();
 
 		    // Plot link
 		    Double yratio = _dataset.getYAxis(iy).getMaxValue()/_dataset.getYAxis(iy).getMinValue();
 		    if(nx==1){
 			writer.element("a");
 			if(_dataset.getYAxis(iy).getMinValue()>0.0 && yratio > 100.0){
 			    writer.attributes("href", baseurl + "/plot" + urlparts + "/x01/ylog" + iy);
 			}
 			else{
 			    writer.attributes("href", baseurl + "/plot" + urlparts + "/x01/y" + iy);
 			}
 			writer.attributes("title", "Display this table in graphical form");
 			writer.write("Plot");
 			writer.end();
 			writer.element("br"); writer.end();
 		    }
 		    else {
 			for (int nxx=1; nxx<=nx; nxx++){
 			    writer.element("a");
 			    if(_dataset.getYAxis(iy).getMinValue()>0.0 && yratio > 100.0){
 				writer.attributes("href", baseurl + "/plot" + urlparts + "/x0"+nxx+"/ylog" + iy);
 			    }
 			    else {
 				writer.attributes("href", baseurl + "/plot" + urlparts + "/x0"+nxx+"/y" + iy);
 			    }
 			    writer.attributes("title", "Display this table in graphical form using xaxis "+nxx);
 			    writer.write("Plot v x"+nxx);
 			    writer.end();
 			    writer.element("br"); writer.end();
 			}
 		    }
 		    // Plot selection link
 		    writer.element("a");
 		    writer.attributes("href", baseurl + "/saveplot?string=" + getSearchString() + "&plot=" +  _dataset.getPaper().getId() + "ds" + _dataset.getId() + "ya" + iy);
 		    writer.attributes("title", "Add this table to the list for combined plotting");
 		    writer.write("SelectPlot");
 		    writer.end();
 
 		    writer.end(); //td
 		}
 		writer.end(); //tr
             }
         } // end "full format only"
 
         writer.end(); //table
 
 	//        writer.element("input");
 	//        if(!getFormat().equals("full")) { writer.attributes("type", "hidden");}
 	//        writer.attributes("name", "string");
 	//        writer.attributes("value", getSearchString());
 	//        writer.end();
 	//
     }
 
 
     @Parameter(name="dataset")
 	private Dataset _dataset;
 
 
     public String forms(Double value) {
         int width = 20;
         return this.forms(value,width);
     }
 
 
     public String forms(Double value, int width) {
         int position = width/2;
         return this.forms(value,width,position);
     }
 
 
     public String forms(Double value, int width, int position) {
         String form = "##############.###############################";
         DecimalFormat myFormatter = new DecimalFormat(form);
         String sval = "Cannot format this!!";
         if( value instanceof Double ){
             sval = myFormatter.format(value);
         }
         String sout = " ";
         for (int i = 1 ; i < width; ++i) {
             sout = sout.concat(" ");
         }
         int lenval = sval.length();
         int dotpos = sval.indexOf(".");
         String before = sval;
         String after = "";
         if (dotpos >= 0) {
             before = sval.substring(0, dotpos);
             after  = sval.substring(dotpos+1, lenval);
         }
         int lenbefore = before.length();
         int lenafter = after.length();
         int lenout = sout.length();
         StringBuffer bout = new StringBuffer(sout);
         int lstart = 1;
         int l1 = lstart + lenbefore;
         int l2 = l1;
         int l3 = l2 + 1;
         int l4 = l3 + lenafter;
 
         bout.replace(lstart, l1,before);
         bout.replace(l2, l2, ".");
         bout.replace(l3, l4, after);
         sout = bout.toString();
 
         return sout;
     }
 
 
     private String getSearchString() {
         return _reqGlobals.getRequest().getParameter("string");
     }
 
 
 }