You are viewing a plain text version of this content. The canonical link for it is here.
Posted to fop-commits@xmlgraphics.apache.org by ar...@apache.org on 2001/02/10 04:20:32 UTC

cvs commit: xml-fop/src/org/apache/fop/mif MIFDocument.java

arved       01/02/09 19:20:32

  Added:       src/org/apache/fop/mif MIFDocument.java
  Log:
  MIF Document description
  
  Revision  Changes    Path
  1.1                  xml-fop/src/org/apache/fop/mif/MIFDocument.java
  
  Index: MIFDocument.java
  ===================================================================
  /*-- $Id: MIFDocument.java,v 1.1 2001/02/10 03:20:32 arved Exp $ --
  
   ============================================================================
                     The Apache Software License, Version 1.1
   ============================================================================
   
      Copyright (C) 1999 The Apache Software Foundation. All rights reserved.
   
   Redistribution and use in source and binary forms, with or without modifica-
   tion, are permitted provided that the following conditions are met:
   
   1. Redistributions of	source code must  retain the above copyright  notice,
      this list of conditions and the following disclaimer.
   
   2. Redistributions in binary form must reproduce the above copyright notice,
      this list of conditions and the following disclaimer in the documentation
      and/or other materials provided with the distribution.
   
   3. The end-user documentation included with the redistribution, if any, must
      include  the following	acknowledgment:  "This product includes  software
      developed  by the  Apache Software Foundation  (http://www.apache.org/)."
      Alternately, this  acknowledgment may  appear in the software itself,  if
      and wherever such third-party acknowledgments normally appear.
   
   4. The names "FOP" and  "Apache Software Foundation"  must not be used to
      endorse  or promote  products derived  from this  software without	prior
      written permission. For written permission, please contact
      apache@apache.org.
   
   5. Products  derived from this software may not  be called "Apache", nor may
      "Apache" appear  in their name,  without prior written permission  of the
      Apache Software Foundation.
   
   THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES,
   INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
   FITNESS  FOR A PARTICULAR	PURPOSE ARE  DISCLAIMED.  IN NO  EVENT SHALL  THE
   APACHE SOFTWARE  FOUNDATION  OR ITS CONTRIBUTORS  BE LIABLE FOR  ANY DIRECT,
   INDIRECT, INCIDENTAL, SPECIAL,  EXEMPLARY, OR CONSEQUENTIAL  DAMAGES (INCLU-
   DING, BUT NOT LIMITED TO, PROCUREMENT	OF SUBSTITUTE GOODS OR SERVICES; LOSS
   OF USE, DATA, OR  PROFITS; OR BUSINESS  INTERRUPTION)	HOWEVER CAUSED AND ON
   ANY  THEORY OF LIABILITY,	WHETHER  IN CONTRACT,  STRICT LIABILITY,  OR TORT
   (INCLUDING  NEGLIGENCE OR	OTHERWISE) ARISING IN  ANY WAY OUT OF THE  USE OF
   THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  
   This software	consists of voluntary contributions made  by many individuals
   on  behalf of the Apache Software	Foundation and was	originally created by
   James Tauber <jt...@jtauber.com>. For more  information on the Apache
   Software Foundation, please see <http://www.apache.org/>.
  
   */
  
  
  //Author : Seshadri G
  
  
  
  package org.apache.fop.mif;
  
  // images are the one place that FOP classes outside this package get
  // referenced and I'd rather not do it
  
  import org.apache.fop.image.FopImage;
  import org.apache.fop.messaging.MessageHandler;
  import org.apache.fop.layout.LinkSet;
  import org.apache.fop.datatypes.ColorSpace;
  
  import org.apache.fop.datatypes.IDReferences;
  import org.apache.fop.layout.Page;
  import org.apache.fop.layout.FontMetric;
  import org.apache.fop.layout.FontDescriptor;
  // Java
  import java.io.*;
  import java.io.PrintWriter;
  import java.util.*;
  import java.awt.Rectangle;
  
  /**
   * class representing a MIF document.
   *
   * The document is built up by calling various methods and then finally
   * output to given filehandle using output method.
   *
   */ 
  public class MIFDocument {
  
      /** the version of MIF supported */
  
  
      protected static final String mifVersion = "5.5";
      protected BookComponent bookComponent;
      private Flow curFlow;    // this is a ref to the current flow which could be a textflow or 
  			     // a table	
      private ID curIDCounter=new ID();	
  
      class ID {
  
  	private int idCounter=1;
  	public int getnewID() {
  
  		return idCounter++;
  	}
  	
      }	
  
      class FontFormat {    
  
  	public FontFormat() { }
  
      }
  
      class ParagraphFormat extends FontFormat {
  
  	public ParagraphFormat() {}
  	int startIndent;
  	int endIndent;
  
  
  
      }
  
      class Document {
  	protected int height;
  	protected int width;
  	public Document() {}
  
  	public void output(OutputStream stream) throws IOException {	
  
  		String mif="\n<Document " + "\n<DPageSize " + width/1000f + " " + height/1000f + " >\n>";
  		byte buf[]=mif.getBytes();	
  
  		stream.write(buf);
  		
  	}
  
      }
  
      
      class PolyLine {
  
  	public PolyLine() {}
      }
  
      class ImportObject {
  
  	private String url;
  	private int x,y,w,h;
  
  	public ImportObject(String url,int x,int y,int w,int h) {
  
  		this.url=url;	
  		this.x=x;
  		this.y=y;
  		this.w=w;
  		this.h=h;
  
  	}
  
  
  	public void output(OutputStream stream) throws IOException {	
  
  
  		String path=this.url;
  
  		//Strip 'file:'
  		path= path.substring(5);
  		String result="";
  		int i;
  		do { // replace all matching '/'
  
  			i=path.indexOf("/");
  			if (i != -1) {
  				result=path.substring(0,i);
  				result += "<c\\>";
  				result += path.substring(i + 1);
  				path=result;
  			}
  
  		} while (i!= -1);
  		
  		String mif="\n<ImportObject" + "\n<ImportObFixedSize Yes>";
  		mif += "\n\t<ImportObFileDI " + "`<c\\>" + path + "'" + " >";
  		mif +="\n\t<ShapeRect " + this.x/1000f + " " + this.y/1000f + " " + this.w/1000f + " " + this.h/1000f + " >";
  
  		mif += "\n> #End ImportObj";			
  		stream.write(mif.getBytes());		
  
  	}
  
      }
  
  	
      class Frame {
  
  	private int ID;
  	private int x,y,w,h;
  	Vector content=new Vector();
  	public Frame(int x, int y, int w, int h) {
  
  		this.ID=curIDCounter.getnewID();
  		this.x=x;
  		this.y=y;
  		this.w=w;
  		this.h=h;
  
  	}
  	
  	public void addContent(ImportObject obj) {
  
  		content.addElement(obj);		
  
  	}
  
  	public void output(OutputStream stream) throws IOException {
  
  		String mif="\n<Frame" + "\n\t<ID " + this.ID + " >";
  		mif += "\n\t<Pen 15>\n\t<Fill 7>\n\t<PenWidth  1.0 >\n\t<Separation 0>\n\t<ObColor `Black'>\n\t<DashedPattern \n\t <DashedStyle Solid> \n >";
  
  		mif +="\n\t<RunaroundGap  6.0 pt>\n\t<RunaroundType None>\n\t<Angle  360.0>\n\t<Float No>\n\t<NSOffset  0.0>\n\t<BLOffset  0>\n\t<Cropped No>\n\t<FrameType Below>\n\t<AnchorAlign Center>";
  
  		mif += "\n\t<ShapeRect " + this.x/1000f + " " + this.y/1000f + " " + this.w/1000f + " "  + this.h/1000f + " >";
  	
  
  		stream.write(mif.getBytes());
  
  		Enumeration e=content.elements();
  		while (e.hasMoreElements()) {
  
  			((ImportObject) e.nextElement()).output(stream);
  		}
  		mif ="\n> #End Frame";
  		stream.write(mif.getBytes());
  
  
  
  	}	
  	public int getID() {
  	
  		return this.ID;
  	}	
  
      }
    
      class TextRect {
  	private int rx,ry,w,h;
  	private int numCols;
  	private int curCol=0; //Current column being processed
  	private int colGap=0;
  	private int textRectID;
  	public TextRect(int numCols) {
  
  		this.numCols=numCols;
  		this.curCol=0;
  		this.textRectID=curIDCounter.getnewID();
  		
  	}
  
  
  	public int getTextRectID() {
  	
  		return textRectID;
  	
  	}
  
  
  	public void setTextRectProp(int left,int top,int width,int height) {
  		
  		if (curCol==0) {
  
  			//Use the left and top margins
  
  			rx=left;
  			ry=top;
  			w=width; // current column width , not the entire span
  			h=height;
  			curCol++;
  			
  		}
  		else if (curCol==1) {
  			// Figure out the column gap and the span of the textrect
  			colGap=left-rx-width;
  			// Next the entire width
  			w=numCols*width + (numCols-1)*colGap;
  			curCol++;
  			
  
  		}
  				
  	}
  
  
  	public void output(OutputStream stream) throws IOException {	
  
  		String mif="\n<TextRect" + "\n\t<ID " + textRectID + ">" + "\n\t<ShapeRect " + rx/1000f + " " +  ry/1000f + " " + w/1000f + " " + h/1000f + ">" ;
  
  		if (numCols>1) {
  			mif += "\n<TRNumColumns " + numCols + ">";
  			mif += "\n<TRColumnGap " + colGap/1000f + ">";
  		}
  
  		mif += "\n> #End TextRect" ;
  		byte buf[]=mif.getBytes();
  		stream.write(buf);
  	}
  
      }
  
      class Page {
  	private String pageType;
  	private String pageTag;
  	private String pageBackground;
  	private Vector textRects;
  	public Page(String pageType, String pageTag, String pageBackground) {
  	
  	       	this.pageType=pageType;
  		this.pageTag=pageTag;
  		this.pageBackground=pageBackground;
  		this.textRects=new Vector();
  	}
  
  	public Page() {
  
  		this.pageType="BodyPage";
  		this.pageBackground="Default";
  		this.textRects=new Vector();
  
  	}
  
  
  	public void addTextRect(int numCols) {
  				
  		TextRect textRect=new TextRect(numCols);
  		this.textRects.addElement(textRect);
  	}
  
  	public TextRect curTextRect() {
  
  		return (TextRect) textRects.lastElement();
  
  	}
  
  
  	
  	public void output(OutputStream stream) throws IOException {
  
  
  		String mif="\n<Page" + "\n\t<PageType " + pageType + ">" + "\n\t<PageBackground " + "`" + pageBackground + "'" + ">";
  
  		byte  buf[]=mif.getBytes();
  
  		stream.write(buf);
  		
  		Enumeration e=textRects.elements();
  
  		while (e.hasMoreElements()) {
  
  			((TextRect) e.nextElement()).output(stream);
  
  		}
  		mif="\n>  #End Page\n";
  		stream.write(mif.getBytes()); 
  
  	}
  
  	
       }
  
      abstract class Flow {    
  
  	public Flow() {}
  	public abstract Para curPara();
  	public abstract void startPara();
      }
  
  
      class TextFlow extends Flow {
  	
  	Vector paras;		
  	private int ID; 	// This ID is used within ParaLine, however it is 
  	        		// logical to keep it unique	to a textflow
  
  	public TextFlow() {
  		
  		
  		//The current textrect into which the textflow goes
  		//is the last created.
  
  		this.ID=((bookComponent.curPage()).curTextRect()).getTextRectID();
  		this.paras=new Vector();
  		
  	}
  	
  
  	public int getTextRectID() {
  
  		return ID;
  
  	}
  
  	public Para curPara() {
  
  		return (Para) paras.lastElement();
  	}
  
  	public void startPara() {
  
  		this.paras.addElement(new Para(ID));
  	}
  
  	public void output(OutputStream stream) throws IOException {	
  		String mif="\n<TextFlow";
  		stream.write(mif.getBytes());
  		Enumeration e=paras.elements();
  		while (e.hasMoreElements()) {
  
  			((Para) e.nextElement()).output(stream);
  		}
  		mif="\n> #End TextFlow";
  		stream.write(mif.getBytes());
  	}
  
       }
  	
  
       class Para  {	     
  	
  	Vector paraLines;
  	int ID; // Same as TextRectID
  	ParagraphFormat pgf=null; // This corresponds to to the block properties
  	public Para() {
  
  		this.ID=0;
  		this.paraLines=new Vector();
  	}
  
  
  	public Para(int ID) {
  	
  		this.ID=ID;
  		this.paraLines=new Vector();
  		
  	}
  
  	public ParaLine curParaLine() {
  		if (paraLines.isEmpty()) {
  			return null;
  		}
  		else {
  			return (ParaLine) paraLines.lastElement();
  		}
  	}
  
  	void startParaLine() {
  		
  		this.paraLines.addElement(new ParaLine(ID));
  
  	}
  
  
  	public void setBlockProp(int startIndent,int endIndent) {
  
  		pgf=new ParagraphFormat();
  		pgf.startIndent=startIndent;
  		pgf.endIndent=endIndent;
  				
  
  	}
  
  
  	public void output(OutputStream stream) throws IOException {	
  
  		String mif="\n<Para";
  		//Is there a block property?
  
  		if (pgf != null) {
  			mif += "\n<Pgf" ;
  			mif += "\n<PgfTag `Body'>";
  			mif += "\n<PgfLIndent " + pgf.startIndent/1000f + ">";
  			mif += "\n<PgfRIndent " + pgf.endIndent/1000f + ">";
  			mif += "\n>";
  		}
  		stream.write(mif.getBytes());
  		Enumeration e=paraLines.elements();
  		while (e.hasMoreElements()) {
  
  			((ParaLine) e.nextElement()).output(stream);
  		}
  		mif="\n> #End ParaLine";
  		stream.write(mif.getBytes());
  
  	}
  	
       }
  
       class ParaLine {
  	Vector content; 
  	int textRectID;
  	String tableID;
  	String aFrameID;
  	public ParaLine(int textRectID) {
  
  		this.textRectID=textRectID;
  		this.content=new Vector();
  
  	}
  	public ParaLine () {
  
  		this.textRectID=0; // There is no ID used, in tables
  		this.content=new Vector();
  	}
  
  	public void addContent(Object obj) {
  
  		this.content.addElement(obj);
  
  	}
  	public void output(OutputStream stream) throws IOException {
  	
  		String mif="\n<ParaLine"; 
  
  		// tables dont need the textrectid
  		if (textRectID != 0) 
  		 	mif += "\n\t<TextRectID " + textRectID + ">";	
  
  		stream.write(mif.getBytes());
  		Enumeration e = this.content.elements();
  	        while (e.hasMoreElements()) {
  
  			Object elem=(Object) e.nextElement();
  			if (elem instanceof String) {
  							
  				// Output newlines as char hard return
  				
  				if (elem == "\n") {
  
  					mif ="\n<Char HardReturn>";
  				}
  				else {
  					mif="\n\t<String `" + elem + "'>";
  				}
  				stream.write(mif.getBytes()); 
  				
  			}
  			else 
  			if (elem instanceof Frame) {
  				
  				mif="\n\t<AFrame " + ((Frame) elem).getID() + " >";
  				stream.write(mif.getBytes()); 
  			}		
  			else
  			if (elem instanceof Tbl) {
  				mif="\n\t<ATbl " + ((Tbl) elem).getID() + " >";
  				stream.write(mif.getBytes()); 
  			}	
  	        }
  		mif="\n> #End ParaLine";
  		stream.write(mif.getBytes());
  	
  	}
       }
   
       
       class PgfCatalog {
  
  	Vector pgfs; // Paragraph formats
  	public PgfCatalog() {}
  
  	public void output(OutputStream stream) throws IOException {
  		String mif="\n<PgfCatalog" + "\n<Pgf" + "\n<PgfTag `Body'>" + "\n>" + "\n>";
  		stream.write(mif.getBytes());
  	}
  
       }
  
       class Color {
  
  	public Color() {}
       }
  
       class ColorCatalog {
  
  	public ColorCatalog() {}
       }
  
  
       class Ruling {
  
  	int penWidth;
  	int pen;
  	int lines;
  	public Ruling() {
  	// Default ruling
  		penWidth=1;
  		pen=0;
  		lines=1;
  	
  
  	}
  
  	public void output(OutputStream stream) throws IOException {
  
  		String mif = "\n<Ruling \n<RulingTag `Default'>";
  		mif +="\n<RulingPenWidth " + penWidth + ">";
  		mif +="\n<RulingPen " + pen + ">";
  		mif +="\n<RulingLines " + lines + ">";
  		mif +="\n>";
  		stream.write(mif.getBytes());
  	}
  
       }
  
       class RulingCatalog {
  	// Contains multiple rulings
  
  	Vector ruling = new Vector();
  	public RulingCatalog() {
  	
  	// Add the defualt ruling to the catalog
  
  		ruling.addElement(new Ruling());	
  
  	}
  
  	public void output(OutputStream stream) throws IOException {
  
  		String mif="\n<RulingCatalog";
  		stream.write(mif.getBytes());
  		Enumeration e=ruling.elements();	
  		while (e.hasMoreElements()) {		
  			((Ruling) e.nextElement()).output(stream);
  		}
  		mif="\n> #End RulingCatalog";
  		stream.write(mif.getBytes());
  					
  	}
  
  
       }
  
            
       class TblFormat {
  
  	public TblFormat() {}
       }
  
       class TblCatalog {
  
  	public TblCatalog() {}
  
       }
  	
       class Tbl extends Flow {
  
  	class TblColumn {
  		private int width;
  		public TblColumn(int width) {
  
  			this.width=width;
  
  		}
  		public void output(OutputStream stream) throws IOException {
  
  
  			String mif="\n\t<TblColumnWidth " + width + " >";
  			stream.write(mif.getBytes());				
  
  		}
  
  		
     	}
  
  	class Row {
  		
  		class Cell {
  
  			private int rowSpan,colSpan;
  			private Vector paras; // Paras
  			public Cell(int rowSpan,int colSpan) {
  
  				this.rowSpan=rowSpan;
  				this.colSpan=colSpan;
  				paras=new Vector();
  
  			}
  			public void startPara() {
  
  				this.paras.addElement(new Para());
  			}
  			public void output(OutputStream stream) throws IOException {
  
  				String mif="\n\t\t<Cell" + "\n\t\t<CellContent";
  				stream.write(mif.getBytes());	
  				Enumeration e=paras.elements();	
  				while (e.hasMoreElements()) {		
  					((Para) e.nextElement()).output(stream);
  				}			
  				mif="\n\t\t> #End CellContent";
  				mif +="\n\t> #End Cell";
  				stream.write(mif.getBytes());			
  			}
  
  		}	
  		private Vector cells; 
  
  		public void addCell(int rowSpan, int colSpan) {
  
  			cells.addElement(new Cell(rowSpan,colSpan));
  		}
  
  		public Row() {
  
  			cells=new Vector();
  	
  		}
  		public Cell curCell() {
  
  			return (Cell) this.cells.lastElement();
  		}
  
  		public void output(OutputStream stream) throws IOException {
  
  			String mif="\n\t<Row";
  			stream.write(mif.getBytes());
  			Enumeration e=cells.elements();	
  			while (e.hasMoreElements()) {		
  				((Cell) e.nextElement()).output(stream);
  			}			
  			mif="\n\t> #End Row";
  			stream.write(mif.getBytes());			
  
  		}
  
  
       	}
  
  	private int ID;
  	private Vector tblColumns=new Vector();
  	private Vector tblBody,tblHead,tblFoot;
  	private Vector current; // is a reference to one of tblHead,tblBody or tblFoot
  	public void addColumn(int colWidth) {
  
  		tblColumns.addElement(new TblColumn(colWidth));
  
  	}
  	public void setCurrent(String current) {
  
  		if (current == "fo:table-body") {
  			this.current=this.tblBody;
  		}
  		else
  		if (current == "tablehead") {
  			this.current=this.tblHead;
  		}
  		else
  		if (current == "tablefoot") {
  			this.current=this.tblFoot;
  		}
  	}
  	public void startRow() {
  
  		this.current.addElement(new Row());
  	}
  
  	public void startCell(int rowSpan,int colSpan) {
  
  		//Add a cell into the current row
  
  		((Row) this.current.lastElement()).addCell(rowSpan,colSpan);
  
  	}
  
  	public Tbl() {
  
  		this.ID=curIDCounter.getnewID();
  		tblBody=new Vector();
  		tblHead=new Vector();
  		tblFoot=new Vector();
  
  	}
  
  	public int getID() {
  
  		return this.ID;
  	}	
  	public Para curPara() {
  
  		// Return the last para of the current cell
  
  		Row curRow;
  		curRow= (Row) this.current.lastElement();
  		return (Para) curRow.curCell().paras.lastElement();
  
  
  	}
  	public void startPara() {
  
  		// start a new para in the current cell
  		Row curRow;
  		curRow= (Row) this.current.lastElement();
  		curRow.curCell().startPara();
  
  	}
  
  
  	public void output(OutputStream stream) throws IOException {
  
  		String mif="\n<Tbl" + "\n\t<TblID " + ID + " >";
  
  		// note tbl format to be added in a later release
  		mif += "\n<TblTag Body>" + "\n<TblFormat";
  		mif +="\n<TblColumnRuling `Default'>";
  		mif +="\n<TblBodyRowRuling `Default'>";
  		mif +="\n<TblLRuling `Default'>";
  		mif +="\n<TblBRuling `Default'>";
  		mif +="\n<TblRRuling `Default'>";
  		mif +="\n<TblTRuling `Default'>";
  
  		mif += "\n> #End TblFormat";
   ;
  		mif +="\n\t<TblNumColumns " + tblColumns.size() + " >";				
  		stream.write(mif.getBytes());
  		
  		if (! tblHead.isEmpty()) {
  			Enumeration e=tblHead.elements();	
  			while (e.hasMoreElements()) {		
  				((Row) e.nextElement()).output(stream);
  			}
  		}
  		if (! tblFoot.isEmpty()) {
  			Enumeration e=tblFoot.elements();	
  			while (e.hasMoreElements()) {		
  				((Row) e.nextElement()).output(stream);
  			}
  		}
  		if (! tblBody.isEmpty()) {
  			mif="\n\t<TblBody";
  			stream.write(mif.getBytes());
  			Enumeration e=tblBody.elements();	
  			while (e.hasMoreElements()) {		
  				((Row) e.nextElement()).output(stream);
  			}
  			mif="\n\t> #End tblBody";
  		}
  		mif +="\n> #End Table";
  		stream.write(mif.getBytes());	
  	}
  
       }
  
       class XRefFormat {
  
  	public XRefFormat() {}
       }
  
       class CrossRefInfo {
  
  	public CrossRefInfo() {}
       }
  
       class XRef {
  
  	public XRef() {}
       }
  
       class Marker {
  
  	public Marker() {}
  
       }
  
       class BookComponent {
  
  	Document document;
  	ColorCatalog colorCatalog;
  	RulingCatalog rulingCatalog;
  	PgfCatalog pgfCatalog;
  	TblCatalog tblCatalog;
  	Vector aFrames =  new Vector();
          Vector tables =  new Vector();
  	Vector pages =  new Vector();
  	Vector textFlows =  new Vector();	
  	
  	
  	public BookComponent() {
  	
  		document=null; // Initially no values are available    
  		pgfCatalog = new PgfCatalog();
  		rulingCatalog=new RulingCatalog();
  	}
  
  
  	public Frame createFrame(int x, int y,int w,int h) {
  
  		Frame frame=new Frame(x,y,w,h);
  		aFrames.addElement(frame);	
  		return frame;
  		
  	}
  
  	public Frame curFrame() {
  
  		return (Frame) aFrames.lastElement();
  
  	}
  
  	public TextFlow curTextFlow() {
  
  		return (TextFlow) textFlows.lastElement();
  
  	}
  
  	public Tbl createTable() {
  
  		Tbl table=new Tbl();
  		tables.addElement(table);
  		return table;
  	}
  	public Tbl curTable() {
  		
  		return (Tbl) tables.lastElement();
  	}
  
  	public void output(OutputStream stream) throws IOException {
  	    String mif="<MIFFile 5.00>" + "\n<Units Upt>"	;		
  	    stream.write(mif.getBytes());
  	    pgfCatalog.output(stream);	
  	    rulingCatalog.output(stream);	
  	    document.output(stream);	
  
  	    if (! aFrames.isEmpty()) {
  
  		mif="\n<AFrames";
  		stream.write(mif.getBytes());
  		Enumeration e=aFrames.elements();	
  		while (e.hasMoreElements()) {		
  
  			((Frame) e.nextElement()).output(stream);
  		}
  		
  	        mif="\n>";
  	        stream.write(mif.getBytes());
  	    }
  
  	    if (! tables.isEmpty()) {
  
  		mif="\n<Tbls";
  		stream.write(mif.getBytes());
  		Enumeration e=tables.elements();	
  		while (e.hasMoreElements()) {		
  
  			((Tbl) e.nextElement()).output(stream);
  		}
  		
  	        mif="\n>";
  	        stream.write(mif.getBytes());
  	    }
  	
      
  	    Enumeration e = pages.elements();
  	    while (e.hasMoreElements()) {
  
  		((Page) e.nextElement()).output(stream);
  	    }
  
  	    e=textFlows.elements();
      	    while (e.hasMoreElements()) {
  
  		((TextFlow) e.nextElement()).output(stream);
  
  	    }
  	
  		    		
  	}
  
  
  	private Page curPage() {
  
  	    return (Page) pages.lastElement();			
  
  	}
  
  
  
       }
  
       class ElementSet {
  
  	public ElementSet() {}
  
       }
  
       	    
      /**
       * creates an empty MIF document
       */
      public MIFDocument() {
  		
  	bookComponent = new BookComponent();
        
      }
  	
      public void createPage () {
  
  	bookComponent.pages.addElement(new Page());
  	
      }
  
      
      public void addToStream(String s) {
  
  	//Add this string to the curent flow
  	
  	Para para= curFlow.curPara();
  	ParaLine paraLine= para.curParaLine();
  	paraLine.addContent(s);
  
      }
  
  
  	
  
      public void output(OutputStream stream) throws IOException {
  
  
  	//Output the contents of bookComponent
  
  	this.bookComponent.output(stream);
  
     }
  
  
      public void setDocumentHeightWidth (int height, int width) {
  
  	if (bookComponent.document == null) {
  
  		bookComponent.document=new Document();
  		bookComponent.document.height=height;
  		bookComponent.document.width=width;
    	}
  
  	else if(bookComponent.document.height != height || bookComponent.document.width != width) 	{
  
  		MessageHandler.logln("Warning : FrameMaker doesnt support different page-sizes 		in a document");		
  	}
  
     }
  
  
  
     public void createTextRect(int numCols) {
  	
  	
  	//Create a textrect on the bodypage with these dimensions
  	//This default behaviour will later be changed to reflect on 
  	//the master-page
  
  	
  	(bookComponent.curPage()).addTextRect(numCols);	
  
  
  	// Then create a textflow corresponding to this textrect
  
  	curFlow=new TextFlow();
  	bookComponent.textFlows.addElement(curFlow);
  
     }
  
  
     public void setTextRectProp(int left,int top, int width,int height) {
  	
  	
  	(bookComponent.curPage()).curTextRect().setTextRectProp(left,top,width,height);
  
     
     } 
  
  
      public void startLine() {
  
  				
  	if (curFlow.curPara().curParaLine() != null) {
  		this.addToStream("\n");
  		curFlow.curPara().startParaLine();
  	}
  	else 
  		curFlow.curPara().startParaLine();
  				
  	
    }
  		
  
    public void setBlockProp(int startIndent,int endIndent) {
  
  	
  	curFlow.startPara(); //Start a para
  	curFlow.curPara().setBlockProp(startIndent,endIndent);
  	
    }
  
    public void createFrame(int x, int y, int w, int h) {
  
  	//Create a new anchored frame 
  
  	bookComponent.createFrame(x,y,w,h);	
  
    }
  
  
  
    public void addImage(String url,int x,int y,int w,int h) {
  
  	Frame frame=bookComponent.createFrame(x,y,w,h);
  	ImportObject imageObject=new ImportObject(url,0,0,w,h);
  	frame.addContent(imageObject);
  	if (curFlow.curPara().curParaLine() == null) {
  		curFlow.curPara().startParaLine();
  		
  	}
  	curFlow.curPara().curParaLine().addContent(frame);
  			
  		
    }
  
    public void createTable() {
  
  	// First create a table with an ID, then add it to the textflow
  
  	Tbl table=bookComponent.createTable();
  	if (curFlow.curPara().curParaLine() == null) {
  		curFlow.curPara().startParaLine();
  		
  	}
  	curFlow.curPara().curParaLine().addContent(table);
  
  	/* The above would have added the table to the textflow
  	   But now the flow goes into the table, so ... */
  
  	curFlow=table;
  
    }
  
    public void setColumnProp(int colWidth) {
  
  
  	//Get the current table
  
  	Tbl table=bookComponent.curTable();
  	table.addColumn(colWidth);
  
  
    } 
  
    public void setCurrent(String current) {
  
  	//Start the table body or header or footer
  	Tbl table=bookComponent.curTable();
  	table.setCurrent(current);
  
    }
  
    public void startRow() {
  
  	Tbl table=bookComponent.curTable();
  	table.startRow();	
  
  
    }
  
    public void startCell(int rowSpan,int colSpan) {
  	
  	Tbl table=bookComponent.curTable();
  	table.startCell(rowSpan,colSpan);
  
    }
  
    public void endTable() {
  
  	// Switch the ref back to the current textflow
  
  	curFlow=bookComponent.curTextFlow();
  
    }
  
  
       
   }