[Code2PDF-SVN-commits] SF.net SVN: code-2-pdf: [2] trunk
Status: Beta
                
                Brought to you by:
                
                    m_dreier
                    
                
            | 
      
      
      From: SVN C. to t. C. p. <cod...@li...> - 2007-03-01 12:10:51
      
     | 
| Revision: 2
          http://code-2-pdf.svn.sourceforge.net/code-2-pdf/?rev=2&view=rev
Author:   m_dreier
Date:     2007-03-01 04:10:45 -0800 (Thu, 01 Mar 2007)
Log Message:
-----------
Initial import.
Added Paths:
-----------
    trunk/.classpath
    trunk/.project
    trunk/.settings/
    trunk/.settings/org.eclipse.jdt.ui.prefs
    trunk/build/
    trunk/build.xml
    trunk/src/
    trunk/src/de/
    trunk/src/de/dreiersoftware/
    trunk/src/de/dreiersoftware/source2pdf/
    trunk/src/de/dreiersoftware/source2pdf/DefaultLineParser.java
    trunk/src/de/dreiersoftware/source2pdf/JavaLineParser.java
    trunk/src/de/dreiersoftware/source2pdf/LineParser.java
    trunk/src/de/dreiersoftware/source2pdf/LineParserFactory.java
    trunk/src/de/dreiersoftware/source2pdf/PageEventHandler.java
    trunk/src/de/dreiersoftware/source2pdf/S2PUI.java
    trunk/src/de/dreiersoftware/source2pdf/S2Pcli.java
    trunk/src/de/dreiersoftware/source2pdf/Source2PDF.java
    trunk/src/de/dreiersoftware/source2pdf/package_info.java
Added: trunk/.classpath
===================================================================
--- trunk/.classpath	                        (rev 0)
+++ trunk/.classpath	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<classpath>
+	<classpathentry kind="src" path="src"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/iText"/>
+	<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/Commons CLI"/>
+	<classpathentry kind="output" path="bin"/>
+</classpath>
Added: trunk/.project
===================================================================
--- trunk/.project	                        (rev 0)
+++ trunk/.project	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,17 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<projectDescription>
+	<name>Source2PDF</name>
+	<comment></comment>
+	<projects>
+	</projects>
+	<buildSpec>
+		<buildCommand>
+			<name>org.eclipse.jdt.core.javabuilder</name>
+			<arguments>
+			</arguments>
+		</buildCommand>
+	</buildSpec>
+	<natures>
+		<nature>org.eclipse.jdt.core.javanature</nature>
+	</natures>
+</projectDescription>
Added: trunk/.settings/org.eclipse.jdt.ui.prefs
===================================================================
--- trunk/.settings/org.eclipse.jdt.ui.prefs	                        (rev 0)
+++ trunk/.settings/org.eclipse.jdt.ui.prefs	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,3 @@
+#Thu Mar 01 13:03:35 CET 2007
+eclipse.preferences.version=1
+org.eclipse.jdt.ui.text.custom_code_templates=<?xml version\="1.0" encoding\="UTF-8"?><templates/>
Added: trunk/build.xml
===================================================================
--- trunk/build.xml	                        (rev 0)
+++ trunk/build.xml	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- WARNING: Eclipse auto-generated file.
+              Any modifications will be overwritten.
+              To include a user specific buildfile here, simply create one in the same
+              directory with the processing instruction <?eclipse.ant.import?>
+              as the first entry and export the buildfile again. -->
+<project basedir="." default="jar" name="Source2PDF">
+    <property environment="env"/>
+    <property name="debuglevel" value="source,lines,vars"/>
+    <property name="target" value="1.5"/>
+    <property name="source" value="1.5"/>
+    <path id="iText.userclasspath">
+        <pathelement location="../../../../Developer/Java/Libraries/itext-2.0.0.jar"/>
+    </path>
+    <path id="Commons CLI.userclasspath">
+        <pathelement location="../../../../Developer/Java/Libraries/commons-cli-1.0/commons-cli-1.0.jar"/>
+    </path>
+    <path id="Source2PDF.classpath">
+        <pathelement location="."/>
+        <path refid="iText.userclasspath"/>
+        <path refid="Commons CLI.userclasspath"/>
+    </path>
+	
+    <target name="init" depends="clean">
+    		<mkdir dir="build"/>
+    		<mkdir dir="build/lib"/>
+    		<copy todir="build/lib">
+    			<fileset file="../../../../Developer/Java/Libraries/itext-2.0.0.jar"/>
+    			<fileset file="../../../../Developer/Java/Libraries/commons-cli-1.0/commons-cli-1.0.jar" />
+    		</copy>
+    </target>
+	
+    <target name="clean">
+        <delete>
+	          <fileset dir="build"/>
+        </delete>
+    </target>
+	
+    <target depends="init" name="build">
+        <echo message="${ant.project.name}: ${ant.file}"/>
+        <javac debug="true" debuglevel="${debuglevel}" destdir="bin" source="${source}" target="${target}">
+            <src path="src"/>
+            <classpath refid="Source2PDF.classpath"/>
+        </javac>
+    </target>
+	
+		<target depends="build" name="jar">
+			<jar destfile="build/Source2PDF.jar">
+				<fileset dir="bin" />
+				<manifest>
+					<attribute name="Manifest-Version" value="1.0" />
+					<attribute name="Class-Path" value="lib/itext-2.0.0.jar lib/commons-cli-1.0.jar" />
+					<attribute name="Main-Class" value="de.dreiersoftware.source2pdf.S2PUI" />
+				</manifest>
+			</jar>
+			<zip destfile="build/Source2PDF-bin.zip">
+				<fileset dir="build" />
+			</zip>
+			<zip destfile="build/Source2PDF-src.zip">
+				<fileset dir="src" />
+			</zip>
+		</target>
+</project>
Added: trunk/src/de/dreiersoftware/source2pdf/DefaultLineParser.java
===================================================================
--- trunk/src/de/dreiersoftware/source2pdf/DefaultLineParser.java	                        (rev 0)
+++ trunk/src/de/dreiersoftware/source2pdf/DefaultLineParser.java	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,99 @@
+/**
+ * DefaultLineParser.java
+ * 
+ * Created 25.02.2007 21:08:20 by Martin Dreier <mar...@we...>
+ * 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Source2PDF application.
+ *
+ * The Initial Developer of the Original Code is
+ * Martin Dreier (mar...@we...).
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package de.dreiersoftware.source2pdf;
+
+import com.lowagie.text.Chunk;
+import com.lowagie.text.Font;
+import com.lowagie.text.Paragraph;
+
+/**
+ * A default parser which does no special formatting.
+ * 
+ * @author Martin Dreier <mar...@we...>
+ *
+ */
+public class DefaultLineParser implements LineParser
+{
+
+	/**
+	 * The default font for the text.
+	 */
+	private Font font;
+	
+	/**
+	 * Create a new line parser.
+	 */
+	public DefaultLineParser()
+	{
+		font = new Font();
+	}
+	
+	/**
+	 * @see de.dreiersoftware.source2pdf.LineParser#parseLine(java.lang.String, com.lowagie.text.Paragraph)
+	 */
+	public void parseLine(String line, Paragraph paragraph)
+	{
+		paragraph.add(new Chunk(line, font));
+	}
+
+	/**
+	 * @see de.dreiersoftware.source2pdf.LineParser#setCodeFont(com.lowagie.text.Font)
+	 */
+	public void setCodeFont(Font codeFont)
+	{
+		//No action
+	}
+
+	/**
+	 * @see de.dreiersoftware.source2pdf.LineParser#setCommentFont(com.lowagie.text.Font)
+	 */
+	public void setCommentFont(Font commentFont)
+	{
+		//No action
+	}
+
+	/**
+	 * @see de.dreiersoftware.source2pdf.LineParser#setKeywordFont(com.lowagie.text.Font)
+	 */
+	public void setKeywordFont(Font keywordFont)
+	{
+		//No action
+	}
+
+}
Added: trunk/src/de/dreiersoftware/source2pdf/JavaLineParser.java
===================================================================
--- trunk/src/de/dreiersoftware/source2pdf/JavaLineParser.java	                        (rev 0)
+++ trunk/src/de/dreiersoftware/source2pdf/JavaLineParser.java	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,210 @@
+/**
+ * JavaLineParser.java
+ * Created 25.02.2007 18:03:42 by Martin Dreier <mar...@we...>
+ * 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Source2PDF application.
+ *
+ * The Initial Developer of the Original Code is
+ * Martin Dreier (mar...@we...).
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package de.dreiersoftware.source2pdf;
+
+import java.util.HashSet;
+import java.util.StringTokenizer;
+
+import com.lowagie.text.Chunk;
+import com.lowagie.text.Font;
+import com.lowagie.text.Paragraph;
+
+/**
+ * @author Martin Dreier <mar...@we...>
+ *
+ */
+public class JavaLineParser implements LineParser
+{
+	/**
+	 * Characters that end a word. Used by the line tokenizer.
+	 */
+	private static final String nonWordChars = " .;()[]{}<>\"";
+
+	/**
+	 * A list of all Java keywords as of version 1.5.
+	 */
+	private static String[] java15keywords = new String[]{
+		"abstract", "continue", "for", "new", "switch", "assert",
+		"default", "goto", "package", "synchronized", "boolean",
+		"do", "if", "private", "this", "break", "double", 
+		"implements", "protected", "throw", "byte", "else", "import",
+		"public", "throws", "case", "enum", "instanceof", "return", 
+		"transient", "catch", "extends", "int", "short", "try", 
+		"char", "final", "interface", "static", "void", "class", 
+		"finally", "long", "strictfp", "volatile", "const", "float",
+		"native", "super", "while"
+	};
+	
+	/**
+	 * Hashed set of the keywords to ensure faster access for the
+	 * existence check.
+	 */
+	private HashSet<String> keywords;
+	
+	/**
+	 * Font for the code.
+	 */
+	private Font codeFont;
+	
+	/**
+	 * Font for code keywords.
+	 */
+	private Font keywordFont;
+	
+	/**
+	 * Font for comments.
+	 */
+	private Font commentFont;
+	
+	/**
+	 * Currently in a multi-line comment.
+	 */
+	private boolean inComment = false;
+	
+	/**
+	 * Set up the java line parser.
+	 */
+	public JavaLineParser()
+	{
+		//Set up all fonts to a default font
+		this.codeFont = new Font(Font.COURIER, Font.DEFAULTSIZE, Font.NORMAL);
+		this.commentFont = this.codeFont;
+		this.keywordFont = this.codeFont;
+		//Initialize keyword list
+		initKeywords();
+	}
+	
+	/**
+	 * Set up the Java line parser.
+	 * @param codeFont The font for normal code
+	 * @param commentFont The font for comments
+	 * @param keywordFont The font for langauge keywords
+	 */
+	public JavaLineParser(Font codeFont, Font commentFont, Font keywordFont)
+	{
+		this.codeFont = codeFont;
+		this.commentFont = commentFont;
+		this.keywordFont = keywordFont;
+		//Initialize keyword list
+		initKeywords();
+	}
+	
+	/**
+	 * Initialize the keyword list.
+	 */
+	private void initKeywords()
+	{
+		keywords = new HashSet<String>((int)(java15keywords.length * 1.5));
+		for (String keyword: java15keywords)
+		{
+			keywords.add(keyword);
+		}
+	}
+
+	/**
+	 * @see de.dreiersoftware.source2pdf.LineParser#parseLine(java.lang.String, com.lowagie.text.Paragraph)
+	 */
+	public void parseLine(String line, Paragraph paragraph)
+	{
+		String trimmedLine = line.trim();
+		if (trimmedLine.startsWith("//"))
+		{
+			//One line comment
+			paragraph.add(new Chunk(line, commentFont));
+		}
+		else if (inComment)
+		{
+			//multiline comment (continued)
+			paragraph.add(new Chunk(line, commentFont));
+			if (trimmedLine.endsWith("*/"))
+			{
+				inComment = false;
+			}
+		}
+		else if (trimmedLine.startsWith("/*"))
+		{
+			//multilineComment
+			paragraph.add(new Chunk(line, commentFont));
+			if (!trimmedLine.endsWith("*/"))
+			{
+				inComment = true;
+			}
+		}
+		else
+		{
+			StringTokenizer tokenizer = new StringTokenizer(line, nonWordChars, true);
+			while (tokenizer.hasMoreTokens())
+			{
+				String token = tokenizer.nextToken();
+				if (keywords.contains(token.trim()))
+				{
+					paragraph.add(new Chunk(token, keywordFont));
+				}
+				else
+				{
+					paragraph.add(new Chunk(token, codeFont));
+				}
+			}
+		}
+	}
+
+	/**
+	 * @see de.dreiersoftware.source2pdf.LineParser#setCodeFont(com.lowagie.text.Font)
+	 */
+	public void setCodeFont(Font codeFont)
+	{
+		this.codeFont = codeFont;
+	}
+
+	/**
+	 * @see de.dreiersoftware.source2pdf.LineParser#setCommentFont(com.lowagie.text.Font)
+	 */
+	public void setCommentFont(Font commentFont)
+	{
+		this.commentFont = commentFont;
+	}
+
+	/**
+	 * @see de.dreiersoftware.source2pdf.LineParser#setKeywordFont(com.lowagie.text.Font)
+	 */
+	public void setKeywordFont(Font keywordFont)
+	{
+		this.keywordFont = keywordFont;
+	}
+
+}
Added: trunk/src/de/dreiersoftware/source2pdf/LineParser.java
===================================================================
--- trunk/src/de/dreiersoftware/source2pdf/LineParser.java	                        (rev 0)
+++ trunk/src/de/dreiersoftware/source2pdf/LineParser.java	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,76 @@
+/**
+ * LineParser.java
+ * Created 25.02.2007 18:01:53 by Martin Dreier <mar...@we...>
+ * 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Source2PDF application.
+ *
+ * The Initial Developer of the Original Code is
+ * Martin Dreier (mar...@we...).
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package de.dreiersoftware.source2pdf;
+
+import com.lowagie.text.Font;
+import com.lowagie.text.Paragraph;
+
+/**
+ * LineParsers parse a line of code. A parser must only be used for
+ * one complete file.
+ * 
+ * @author Martin Dreier <mar...@we...>
+ *
+ */
+public interface LineParser
+{
+	/**
+	 * Parse a line of code.
+	 * @param line The current line
+	 * @param paragraph The current paragraph
+	 */
+	public void parseLine(String line, Paragraph paragraph);
+	
+	/**
+	 * Set the font for code. 
+	 * @param codeFont The code font
+	 */
+	public void setCodeFont(Font codeFont);
+	
+	/**
+	 * Set the code for comments.
+	 * @param commentFont The comment font
+	 */
+	public void setCommentFont(Font commentFont);
+	
+	/**
+	 * Set the code for keywords.
+	 * @param keywordFont The keyword font
+	 */
+	public void setKeywordFont(Font keywordFont);
+}
Added: trunk/src/de/dreiersoftware/source2pdf/LineParserFactory.java
===================================================================
--- trunk/src/de/dreiersoftware/source2pdf/LineParserFactory.java	                        (rev 0)
+++ trunk/src/de/dreiersoftware/source2pdf/LineParserFactory.java	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,101 @@
+/**
+ * LineParserFactory.java
+ * Created 25.02.2007 21:04:27 by Martin Dreier <mar...@we...>
+ * 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Source2PDF application.
+ *
+ * The Initial Developer of the Original Code is
+ * Martin Dreier (mar...@we...).
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package de.dreiersoftware.source2pdf;
+
+import java.io.File;
+
+/**
+ * Get the right parser for a file.
+ * 
+ * @author Martin Dreier <mar...@we...>
+ *
+ */
+public class LineParserFactory
+{
+	/**
+	 * Default parser type.
+	 */
+	public static final int DEFAULT = 0;
+	
+	/**
+	 * Java parser type.
+	 */
+	public static final int JAVA = 1;
+	
+	/**
+	 * Get the parser for a file type identifed by the file name.
+	 * 
+	 * @param filename The file name
+	 * @return The parser for that file type
+	 */
+	public static LineParser getParserForFile(File filename)
+	{
+		String file = filename.getName();
+		int lastDot = file.lastIndexOf(".");
+		String extension = "";
+		if (lastDot >= 0)
+		{
+			extension = file.substring(lastDot + 1).toLowerCase();
+		}
+		if (extension.equals("java"))
+		{
+			return getParserByType(JAVA);
+		}
+		else
+		{
+			return getParserByType(DEFAULT);
+		}
+	}
+	
+	/**
+	 * Get the parser by type.
+	 * @param type The parser type
+	 * @return The parser
+	 */
+	public static LineParser getParserByType(int type)
+	{
+		switch (type)
+		{
+			case JAVA:
+				return new JavaLineParser();
+			case DEFAULT:
+			default:
+				return new DefaultLineParser();
+		}
+	}
+}
Added: trunk/src/de/dreiersoftware/source2pdf/PageEventHandler.java
===================================================================
--- trunk/src/de/dreiersoftware/source2pdf/PageEventHandler.java	                        (rev 0)
+++ trunk/src/de/dreiersoftware/source2pdf/PageEventHandler.java	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,225 @@
+/**
+ * PageEventHandler.java
+ * Created 25.02.2007 16:00:11 by Martin Dreier <mar...@we...>
+ * 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Source2PDF application.
+ *
+ * The Initial Developer of the Original Code is
+ * Martin Dreier (mar...@we...).
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package de.dreiersoftware.source2pdf;
+
+import java.util.List;
+
+import com.lowagie.text.Document;
+import com.lowagie.text.Element;
+import com.lowagie.text.ExceptionConverter;
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.pdf.PdfPCell;
+import com.lowagie.text.pdf.PdfPTable;
+import com.lowagie.text.pdf.PdfPageEventHelper;
+import com.lowagie.text.pdf.PdfWriter;
+
+import de.dreiersoftware.source2pdf.Source2PDF.DocChapter;
+import de.dreiersoftware.source2pdf.Source2PDF.DocSection;
+
+/**
+ * Handler for page events.
+ * 
+ * @author Martin Dreier <mar...@we...>
+ *
+ */
+public class PageEventHandler extends PdfPageEventHelper
+{
+	/**
+	 * The author's name.
+	 */
+	private String author;
+	
+	/**
+	 * The document title.
+	 */
+	private String title;
+
+	/**
+	 * The copyright notice.
+	 */
+	private String copyright;
+	
+	/**
+	 * A list of chapters.
+	 */
+	private List<DocChapter> chapters;
+	
+	/**
+	 * The current chapter.
+	 */
+	private DocChapter current;
+	
+	/**
+	 * The current section
+	 */
+	private DocSection currentSection;
+	
+	/**
+	 * Page number for the table of contents.
+	 */
+	private int tocPageNumber = 1;
+	
+	/**
+	 * Create a new handler.
+	 * @param author The author's name
+	 * @param title The document title
+	 * @param copyright The copyright notice
+	 * @param chapters The lsit of chapters which will be filled
+	 */
+	public PageEventHandler(String author, String title, String copyright, List<DocChapter> chapters)
+	{
+		this.author = author;
+		this.title = title;
+		this.copyright = copyright;
+		this.chapters = chapters;
+	}
+	
+	/**
+	 * @see PdfPageEventHelper#onEndPage(PdfWriter, Document)
+	 */
+	public void onEndPage(PdfWriter writer, Document document)
+	{
+		if (writer.getPageNumber() <= 1)
+		{
+			//Do nothing for title page
+			return;
+		}
+		try 
+		{
+      Rectangle page = document.getPageSize();
+      //Header
+      PdfPTable head = new PdfPTable(2);
+      Paragraph authorP = new Paragraph(author);
+      PdfPCell h = new PdfPCell(authorP);
+      h.setBorderWidthLeft(0);
+      h.setBorderWidthRight(0);
+      h.setBorderWidthTop(0);
+      head.addCell(h);
+      String titleStr = title;
+      if (current.getTitle().equals("Table of Contents"))
+      {
+      	titleStr = current.getTitle();
+      }
+      else if (currentSection != null)
+      {
+      	titleStr += ": " + currentSection.getTitle();
+      }
+      Paragraph titleP = new Paragraph(titleStr);
+      h = new PdfPCell(titleP);
+      h.setHorizontalAlignment(Element.ALIGN_RIGHT);
+      h.setBorderWidthLeft(0);
+      h.setBorderWidthRight(0);
+      h.setBorderWidthTop(0);
+      head.addCell(h);
+      head.setTotalWidth(page.width() - document.leftMargin() - document.rightMargin());
+      head.writeSelectedRows(0, -1, document.leftMargin(), page.height() - document.topMargin() + head.getTotalHeight(),
+          writer.getDirectContent());
+      //Footer
+      PdfPTable foot = new PdfPTable(3);
+      if (copyright != null)
+      {
+      	Paragraph copy = new Paragraph(copyright);
+      	PdfPCell c = new PdfPCell(copy);
+      	c.setBorderWidth(0);
+        foot.addCell(c);
+        c = new PdfPCell();
+        c.setBorder(0);
+        foot.addCell(c);
+        Paragraph pnumber;
+        if (current != null && current.getTitle().equals("Table of Contents"))
+        {
+        	pnumber = new Paragraph(Integer.toString(tocPageNumber++));
+        }
+        else
+        {
+        	pnumber = new Paragraph(Integer.toString(writer.getPageNumber()));
+        }
+        c = new PdfPCell(pnumber);
+        c.setHorizontalAlignment(Element.ALIGN_RIGHT);
+        c.setBorderWidth(0);
+        foot.addCell(c);      	
+      }
+      else
+      {
+      	PdfPCell c = new PdfPCell();
+      	c.setBorderWidth(0);
+        foot.addCell(c);
+        Paragraph pnumber;
+        if (current != null && current.getTitle().equals("Table of Contents"))
+        {
+        	pnumber = new Paragraph(Integer.toString(tocPageNumber++));
+        }
+        else
+        {
+        	pnumber = new Paragraph(Integer.toString(writer.getPageNumber()));
+        }c = new PdfPCell(pnumber);
+        c.setBorderWidth(0);
+        c.setHorizontalAlignment(Element.ALIGN_CENTER);
+        foot.addCell(c);    	
+        c = new PdfPCell();
+        c.setBorder(0);
+        foot.addCell(c);
+      }
+      foot.setTotalWidth(page.width() - document.leftMargin() - document.rightMargin());
+      foot.writeSelectedRows(0, -1, document.leftMargin(), document.bottomMargin(),
+          writer.getDirectContent());
+	  }
+	  catch (Exception e) {
+	      throw new ExceptionConverter(e);
+	  }
+	}
+
+	/**
+	 * @see com.lowagie.text.pdf.PdfPageEventHelper#onChapter(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document, float, com.lowagie.text.Paragraph)
+	 */
+	public void onChapter(PdfWriter writer, Document document, float paragraphPosition, Paragraph title)
+	{
+		current = new DocChapter(writer.getPageNumber(), title.content());
+		chapters.add(current);
+	}
+
+	/**
+	 * @see com.lowagie.text.pdf.PdfPageEventHelper#onSection(com.lowagie.text.pdf.PdfWriter, com.lowagie.text.Document, float, int, com.lowagie.text.Paragraph)
+	 */
+	public void onSection(PdfWriter writer, Document document, float paragraphPosition, int depth, Paragraph title)
+	{
+		currentSection = new DocSection(writer.getPageNumber(), title.content());
+		current.addSection(currentSection);
+	}
+}
Added: trunk/src/de/dreiersoftware/source2pdf/S2PUI.java
===================================================================
--- trunk/src/de/dreiersoftware/source2pdf/S2PUI.java	                        (rev 0)
+++ trunk/src/de/dreiersoftware/source2pdf/S2PUI.java	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,277 @@
+/**
+ * S2PUI.java
+ * Created 25.02.2007 23:35:25 by Martin Dreier <mar...@we...>
+
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Source2PDF application.
+ *
+ * The Initial Developer of the Original Code is
+ * Martin Dreier (mar...@we...).
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package de.dreiersoftware.source2pdf;
+
+import java.awt.BorderLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JFileChooser;
+import javax.swing.JFrame;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+import javax.swing.UIManager;
+import javax.swing.border.Border;
+import javax.swing.border.EtchedBorder;
+
+import com.lowagie.text.PageSize;
+
+/**
+ * A user interface for the Source2PDF application.
+ * 
+ * @author Martin Dreier <mar...@we...>
+ *
+ */
+public class S2PUI extends JFrame
+{
+
+	/**
+	 * For serialization.
+	 */
+	private static final long serialVersionUID = 8753382647908729275L;
+	
+	/**
+	 * The source directory.
+	 */
+	private JTextField source;
+
+	/**
+	 * The target file.
+	 */
+	private JTextField target;
+
+	/**
+	 * The document title.
+	 */
+	private JTextField title;
+
+	/**
+	 * The subtitle.
+	 */
+	private JTextField subtitle;
+
+	/**
+	 * The author's name.
+	 */
+	private JTextField author;
+
+	/**
+	 * The copyright notice.
+	 */
+	private JTextField copyright;
+
+	/**
+	 * The font for normal text.
+	 */
+	private JComboBox font;
+
+	/**
+	 * The font for code.
+	 */
+	private JComboBox codeFont;
+
+	/**
+	 * Create the frame. Also constructs the UI.
+	 */
+	public S2PUI()
+	{
+		super("Source2PDF");
+		try
+		{
+			UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
+		} catch (Exception e)
+		{
+			e.printStackTrace();
+		}
+		setLayout(new BorderLayout(5,5));
+		
+		//Panel on the top
+		JPanel top = new JPanel();
+		top.setLayout(new GridLayout(0,3));
+		//Source file label
+		top.add(new JLabel("Source directory:"));
+		//Source file text field
+		source = new JTextField();
+		top.add(source);
+		//Select source button
+		JButton selectSource = new JButton("Choose...");
+		selectSource.addActionListener(new ActionListener() {
+
+			public void actionPerformed(ActionEvent arg0)
+			{
+				JFileChooser fc = new JFileChooser();
+				fc.setAcceptAllFileFilterUsed(false);
+				fc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+				if (fc.showOpenDialog(null) == JFileChooser.APPROVE_OPTION)
+				{
+					source.setText(fc.getSelectedFile().getAbsolutePath());
+				}
+			}
+			
+		});
+		top.add(selectSource);
+		
+		//Target file label
+		top.add(new JLabel("Target file:"));
+		//Target file text field
+		target = new JTextField();
+		top.add(target);
+		//Select target file button
+		JButton selectTarget = new JButton("Choose...");
+		selectTarget.addActionListener(new ActionListener() {
+
+			public void actionPerformed(ActionEvent arg0)
+			{
+				JFileChooser fc = new JFileChooser();
+				if (fc.showSaveDialog(null) == JFileChooser.APPROVE_OPTION)
+				{
+					target.setText(fc.getSelectedFile().getAbsolutePath());
+				}
+			}
+			
+		});
+		top.add(selectTarget);
+		add(top, BorderLayout.NORTH);
+		
+		//Center panel
+		JPanel center = new JPanel();
+		Border b = new EtchedBorder();
+		center.setBorder(b);
+		center.setLayout(new GridLayout(0, 2));
+		center.add(new JLabel("Document Title:"));
+		title = new JTextField();
+		center.add(title);
+		center.add(new JLabel("Subtitle:"));
+		subtitle = new JTextField();
+		center.add(subtitle);
+		center.add(new JLabel("Author:"));
+		author = new JTextField();
+		center.add(author);
+		center.add(new JLabel("Copyright Notice:"));
+		copyright = new JTextField();
+		center.add(copyright);
+		center.add(new JLabel("Normal Font:"));
+		font = new JComboBox(new Object[] {"Times New Roman", "Helvetica"});
+		center.add(font);
+		center.add(new JLabel("Code Font:"));
+		codeFont = new JComboBox(new Object[] {"Courier"});
+		center.add(codeFont);
+		add(center);
+		
+		//Execute button
+		JButton runButton = new JButton("Run");
+		runButton.addActionListener(new ActionListener() {
+
+			public void actionPerformed(ActionEvent arg0)
+			{
+				run();
+			}
+			
+		});
+		add(runButton, BorderLayout.SOUTH);
+		pack();
+	}
+	
+	/**
+	 * Executes the conversion.
+	 */
+	private void run()
+	{
+		File sourceDir = new File(source.getText());
+		if (!sourceDir.exists())
+		{
+			JOptionPane.showMessageDialog(this, "Source directory " + sourceDir.getName() + " does not exist.", "Error", JOptionPane.ERROR_MESSAGE);
+			return;
+		}
+		File targetFile = new File(target.getText());
+		Source2PDF s2p = new Source2PDF(sourceDir, targetFile);
+		if (!title.getText().equals(""))
+		{
+			s2p.setTitle(title.getText());
+		}
+		if (!author.getText().equals(""))
+		{
+			s2p.setAuthor(author.getText());
+		}
+		if (!subtitle.getText().equals(""))
+		{
+			s2p.setSubtitle(subtitle.getText());
+		}
+		if (!copyright.getText().equals(""))
+		{
+			s2p.setCopyright(copyright.getText());
+		}
+		if (font.getSelectedItem().toString().equals("Times New Roman"))
+		{
+			s2p.setFontFamily("times");
+		}
+		else if (font.getSelectedItem().toString().equals("Helvetica"))
+		{
+			s2p.setFontFamily("helvetica");
+		}
+		if (codeFont.getSelectedItem().toString().equals("Courier"))
+		{
+			s2p.setFontFamily("courier");
+		}
+		try
+		{
+			s2p.convert(PageSize.A4);
+		} catch (Throwable e)
+		{
+			JOptionPane.showMessageDialog(this, e.getClass().getName() + " occurred while processing: " + e.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
+			return;
+		}
+		JOptionPane.showMessageDialog(this, "File successfully written to\n" + targetFile.getAbsolutePath());
+	}
+	
+	/**
+	 * Start the UI.
+	 * @param args Command line arguments
+	 */
+	public static void main(String[] args)
+	{
+		new S2PUI().setVisible(true);
+	}
+
+}
Added: trunk/src/de/dreiersoftware/source2pdf/S2Pcli.java
===================================================================
--- trunk/src/de/dreiersoftware/source2pdf/S2Pcli.java	                        (rev 0)
+++ trunk/src/de/dreiersoftware/source2pdf/S2Pcli.java	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,235 @@
+/**
+ * S2Pcli.java
+ * Created 25.02.2007 16:44:45 by Martin Dreier <mar...@we...>
+ * 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Source2PDF application.
+ *
+ * The Initial Developer of the Original Code is
+ * Martin Dreier (mar...@we...).
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package de.dreiersoftware.source2pdf;
+
+import java.io.File;
+
+import org.apache.commons.cli.CommandLine;
+import org.apache.commons.cli.CommandLineParser;
+import org.apache.commons.cli.GnuParser;
+import org.apache.commons.cli.HelpFormatter;
+import org.apache.commons.cli.Option;
+import org.apache.commons.cli.OptionBuilder;
+import org.apache.commons.cli.Options;
+import org.apache.commons.cli.ParseException;
+
+import com.lowagie.text.PageSize;
+
+/**
+ * Command line interface for the Source2PDF.
+ * 
+ * @author Martin Dreier <mar...@we...>
+ *
+ */
+public class S2Pcli
+{
+
+	/**
+	 * The main method.
+	 * @param args Command line arguments
+	 */
+	public static void main(String[] args)
+	{
+		System.out.println("dreier.software Source2PDF");
+		CommandLineParser parser = new GnuParser();
+		try
+		{
+			CommandLine cl = parser.parse(getOptions(), args);
+			if (cl.hasOption("h"))
+			{
+				//Show usage instructions
+				HelpFormatter hf = new HelpFormatter();
+				hf.printHelp("java de.dreiersoftware.source2pdf.S2Pcli", getOptions());
+				return;
+			}
+			else if (cl.hasOption("v"))
+			{
+				//Show version information
+				System.out.println("dreier.software Source2PDF 1.0 Beta 2");
+				System.out.print("This program is available under the Mozilla Public Licence,");
+				System.out.print("the GNU General Public Licence and the GNU Lesser General Public License");
+				System.out.println("MPL: http://www.mozilla.org/MPL/MPL-1.1.html");
+				System.out.println("GPL: http://www.fsf.org/licensing/licenses/gpl.html");
+				System.out.println("LGPL: http://www.fsf.org/licensing/licenses/lgpl.html");
+				return;
+			}
+			//Source
+			String source = cl.getOptionValue("s");
+			//Output
+			String output = cl.getOptionValue("o");
+			File o = new File(output);
+			Source2PDF s2p = new Source2PDF(new File(source), o);
+			if (cl.hasOption("t"))
+			{
+				//Title
+				s2p.setTitle(cl.getOptionValue("t"));
+			}
+			if (cl.hasOption("u"))
+			{
+				//Subtitle
+				s2p.setSubtitle(cl.getOptionValue("u"));
+			}
+			if (cl.hasOption("c"))
+			{
+				//Copyright notice
+				s2p.setCopyright(cl.getOptionValue("c"));
+			}
+			if (cl.hasOption("a"))
+			{
+				//Author
+				s2p.setAuthor(cl.getOptionValue("a"));
+			}
+			if (cl.hasOption("f"))
+			{
+				//font
+				s2p.setFontFamily(cl.getOptionValue("f"));
+			}
+			if (cl.hasOption("d"))
+			{
+				//Include hidden
+				s2p.setIncludeHidden(true);
+			}
+			if (cl.hasOption("i"))
+			{
+				//Included files
+				s2p.setIncludedFiles(cl.getOptionValue("i"));
+			}
+			if (cl.hasOption("e"))
+			{
+				//Excluded files
+				s2p.setExcludedFiles(cl.getOptionValue("e"));
+			}
+			//Execute A4
+			System.out.println("Starting...");
+			s2p.convert(PageSize.A4);
+			System.out.println("Finished: Document written to " + o.getAbsolutePath());
+		} catch (ParseException e)
+		{
+			System.out.println("Exception parsing the command line:" + e.getMessage());
+		} catch (Exception e)
+		{
+			System.out.println("Error while converting: " + e.getMessage());
+			e.printStackTrace();
+		}
+	}
+	
+	/**
+	 * Get the command line options.
+	 * @return The options
+	 */
+	@SuppressWarnings("static-access")
+	private static Options getOptions()
+	{
+		Option help = new Option("h", false, "Show usage instructions");
+		Option version = new Option("v", false, "Print version information");
+		Option hidden = new Option("d", false, "Include hidden files and folders");
+		
+		Option title = OptionBuilder.withArgName("title").hasArg()
+												.withDescription("Document title")
+												.withLongOpt("title")
+												.create("t");
+		
+		Option subtitle = OptionBuilder.withArgName("subtitle").hasArg()
+											.withDescription("Document subtitle")
+											.withLongOpt("subtitle")
+											.create("u");
+		
+		Option author = OptionBuilder.withArgName("name").hasArg()
+											.withDescription("Author name")
+											.withLongOpt("author")
+											.create("a");
+		
+		Option authorPrefix = OptionBuilder.withArgName("prefix").hasArg()
+											.withDescription("Prefix for the author name on the" +
+													"title page")
+											.withLongOpt("prefix")
+											.create("p");
+		
+		Option font = OptionBuilder.withArgName("fontFamily").hasArg()
+											.withDescription("Font family to use for the text" +
+													"in the document. Possible values: times, helvetica")
+											.withLongOpt("font")
+											.create("f");
+											
+		Option source = OptionBuilder.withArgName("directory").hasArg()
+											.withDescription("Source directory")
+											.withLongOpt("source")
+											.create("s");
+		
+		Option copyright = OptionBuilder.withArgName("text").hasArg()
+											.withDescription("Copyright notice")
+											.withLongOpt("copy")
+											.create("c");
+											
+		Option output = OptionBuilder.withArgName("fileName").hasArg()
+											.withDescription("Output file")
+											.withLongOpt("output")
+											.create("o");
+		
+		Option include = OptionBuilder.withArgName("ext1,ext2,ext3").hasArg()
+											.withDescription("comma-delimited list of file extensions which" +
+													"should be included in the document. If not provided, all" +
+													"files will be included")
+											.withLongOpt("include")
+											.create("i");
+
+		Option exclude = OptionBuilder.withArgName("ext1,ext2,ext3").hasArg()
+											.withDescription("comma-delimited list of file extensions which" +
+													"should be excluded from the document. If not provided, no" +
+													"files will be excluded")
+											.withLongOpt("exclude")
+											.create("e");
+
+		Options options = new Options();
+		options.addOption(source);
+		options.addOption(output);
+		options.addOption(include);
+		options.addOption(exclude);
+		options.addOption(hidden);
+		options.addOption(author);
+		options.addOption(authorPrefix);
+		options.addOption(title);
+		options.addOption(font);
+		options.addOption(subtitle);
+		options.addOption(copyright);
+		options.addOption(help);
+		options.addOption(version);
+		return options;
+	}
+
+}
Added: trunk/src/de/dreiersoftware/source2pdf/Source2PDF.java
===================================================================
--- trunk/src/de/dreiersoftware/source2pdf/Source2PDF.java	                        (rev 0)
+++ trunk/src/de/dreiersoftware/source2pdf/Source2PDF.java	2007-03-01 12:10:45 UTC (rev 2)
@@ -0,0 +1,730 @@
+/**
+ * Source2PDF.java
+ * Created 25.02.2007 15:26:50 by Martin Dreier <mar...@we...>
+ * 
+ * ***** BEGIN LICENSE BLOCK *****
+ * Version: MPL 1.1/GPL 2.0/LGPL 2.1
+ *
+ * The contents of this file are subject to the Mozilla Public License Version
+ * 1.1 (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * Software distributed under the License is distributed on an "AS IS" basis,
+ * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
+ * for the specific language governing rights and limitations under the
+ * License.
+ *
+ * The Original Code is the Source2PDF application.
+ *
+ * The Initial Developer of the Original Code is
+ * Martin Dreier (mar...@we...).
+ * Portions created by the Initial Developer are Copyright (C) 2007
+ * the Initial Developer. All Rights Reserved.
+ *
+ * Alternatively, the contents of this file may be used under the terms of
+ * either the GNU General Public License Version 2 or later (the "GPL"), or
+ * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
+ * in which case the provisions of the GPL or the LGPL are applicable instead
+ * of those above. If you wish to allow use of your version of this file only
+ * under the terms of either the GPL or the LGPL, and not to allow others to
+ * use your version of this file under the terms of the MPL, indicate your
+ * decision by deleting the provisions above and replace them with the notice
+ * and other provisions required by the GPL or the LGPL. If you do not delete
+ * the provisions above, a recipient may use your version of this file under
+ * the terms of any one of the MPL, the GPL or the LGPL.
+ *
+ * ***** END LICENSE BLOCK ***** */
+package de.dreiersoftware.source2pdf;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+import java.util.StringTokenizer;
+
+import com.lowagie.text.Chapter;
+import com.lowagie.text.Chunk;
+import com.lowagie.text.Document;
+import com.lowagie.text.DocumentException;
+import com.lowagie.text.Font;
+import com.lowagie.text.Paragraph;
+import com.lowagie.text.Phrase;
+import com.lowagie.text.Rectangle;
+import com.lowagie.text.Section;
+import com.lowagie.text.pdf.ColumnText;
+import com.lowagie.text.pdf.PdfPageLabels;
+import com.lowagie.text.pdf.PdfWriter;
+
+/**
+ * Convert a directory of source files into one compiled PDF
+ * document.
+ * 
+ * @author Martin Dreier <mar...@we...>
+ *
+ */
+public class Source2PDF
+{
+	
+	/**
+	 * The root source directory.
+	 */
+	private File sourceDir;
+	
+	/**
+	 * The target file.
+	 */
+	private File targetFile;
+	
+	/**
+	 * The document instance.
+	 */
+	private Document document;
+
+	/**
+	 * The title of the result document.
+	 */
+	private String title;
+	
+	/**
+	 * The author of the result document.
+	 */
+	private String author;
+	
+	/**
+	 * The current chapter number.
+	 */
+	private int chapterNumber;
+	
+	/**
+	 * Font for the chapter title.
+	 */
+	private Font chapterFont;
+	
+	/**
+	 * Font for the section title.
+	 */
+	private Font sectionFont;
+	
+	/**
+	 * Font for the code.
+	 */
+	private Font codeFont;
+	
+	/**
+	 * Font for code keywords.
+	 */
+	private Font keywordFont;
+	
+	/**
+	 * Font for comments.
+	 */
+	private Font commentFont;
+
+	/**
+	 * The subtitle.
+	 */
+	private String subtitle;
+
+	/**
+	 * The copyright notice.
+	 */
+	private String copyright;
+
+	/**
+	 * A list of chapters.
+	 */
+	private List<DocChapter> chapters;
+
+	/**
+	 * Font for normal text.
+	 */
+	private Font normalFont;
+
+	/**
+	 * Font family for normal text.
+	 */
+	private int normalFontFamily;
+	
+	/**
+	 * Font family for code.
+	 */
+	private int codeFontFamily;
+
+	/**
+	 * Include hidden files in the document.
+	 */
+	private boolean includeHidden;
+	
+	/**
+	 * A list of excluded file extensions.
+	 */
+	private Set<String> excludedFileExtensions;
+
+	/**
+	 * A list of included file extensions.
+	 */
+	private Set<String> includedFileExtensions;
+
+	/**
+	 * Create a new converter instance.
+	 * @param sourceDir The root source directory
+	 * @param targetFile The target filename
+	 */
+	public Source2PDF(File sourceDir, File targetFile)
+	{
+		this.sourceDir = sourceDir;
+		this.targetFile = targetFile;
+		this.title = sourceDir.getName();
+		this.author = "";
+		//Chapter 1 will be the ToC
+		this.chapterNumber = 2;
+		this.normalFontFamily = Font.TIMES_ROMAN;
+		this.codeFontFamily = Font.COURIER;
+		this.includeHidden = false;
+	}
+	
+	/**
+	 * Set the author of the result document.
+	 * @param name The author's name
+	 */
+	public void setAuthor(String name)
+	{
+		this.author = name;
+	}
+	
+	/**
+	 * Set the title of the document.
+	 * 
+	 * @param title The title
+	 */
+	public void setTitle(String title)
+	{
+		this.title = title;
+	}
+	
+	/**
+	 * Set the subtitle of the document.
+	 * 
+	 * @param subtitle The subtitle
+	 */
+	public void setSubtitle(String subtitle)
+	{
+		this.subtitle = subtitle;
+	}
+	
+	/**
+	 * Set the copyright notice.
+	 * 
+	 * @param copy The copyright notice.
+	 */
+	public void setCopyright(String copy)
+	{
+		this.copyright = copy;
+	}
+	
+	/**
+	 * Start the conversion.
+	 * @throws DocumentException If an error ocurs with the document.
+	 * @throws FileNotFoundException If the target file could not be found.
+	 */
+	public void convert(Rectangle pageSize) throws FileNotFoundException, DocumentException
+	{
+		if (document != null)
+		{
+			//Conversion has already been started
+			throw new IllegalStateException("Conversion already started.");
+		}
+		setupFonts();
+		document = new Document(pageSize);
+		PdfWriter writer = PdfWriter.getInstance(document, new FileOutputStream(targetFile));
+		document.addTitle(title);
+		document.addCreator("dreier.software Source2PDF");
+		document.addAuthor(this.author);
+		document.open();
+		chapters = new LinkedList<DocChapter>();
+		writer.setPageEvent(new PageEventHandler(author, title, copyright, chapters));
+		writer.setLinearPageMode();
+		makeTitlePage();
+		//document.resetPageCount();
+		addDirectory(sourceDir);
+		makeTOC(writer);
+		document.close();
+	}
+	
+	/**
+	 * Create the table of contents.
+	 * @param writer The writer used for the document
+	 * @throws DocumentException When an error occurs
+	 */
+	private void makeTOC(PdfWriter writer) throws DocumentException
+	{
+		int split = writer.getCurrentPageNumber();
+		document.newPage();
+		//document.resetPageCount();
+		Paragraph title = new Paragraph("Table of Contents", chapterFont);
+		Chapter toc = new Chapter(title, 1);
+		toc.setNumberDepth(0);
+		Font chapFont = new Font(Font.TIMES_ROMAN, Font.DEFAULTSIZE + 3, Font.BOLD);
+		Font secFont = new Font(Font.TIMES_ROMAN, Font.DEFAULTSIZE, Font.NORMAL);
+		for (DocChapter chapter: chapters)
+		{
+			toc.add(Chunk.NEWLINE);
+			Paragraph chap = new Paragraph();
+			Phrase chapTitle = new Phrase(chapter.getTitle(), chapFont);
+			Phrase chapNumber = new Phrase(Integer.toString(chapter.getStartPage()), chapFont);
+			addTocLine(chapTitle, chapNumber, chapFont, chap);
+			for (DocSection sec: chapter.getSections())
+			{
+				Phrase secTitle = new Phrase(sec.getTitle(), secFont);
+				Phrase secNumber = new Phrase(Integer.toString(sec.getPage()), secFont);
+				addTocLine(secTitle, secNumber, secFont, chap);
+			}
+			toc.add(chap);
+		}
+		document.add(toc);
+		document.newPage();
+		//Order ToC into front
+    int totalPages = writer.getCurrentPageNumber() - 1;
+    int reorder[] = new int[totalPages];
+    for (int k = split; k <= totalPages; ++k)
+        reorder[k - split + 1] = k;
+    int off = totalPages - split;
+    for (int k = 2; k < split; ++k)
+        reorder[off + k] = k;
+    reorder[0] = 1;
+    writer.reorderPages(reorder);
+    PdfPageLabels labels = new PdfPageLabels();
+    labels.addPageLabel(1, PdfPageLabels.EMPTY);
+    labels.addPageLabel(2, PdfPageLabels.DECIMAL_ARABIC_NUMERALS);
+    writer.setPageLabels(labels);
+	}
+	
+	/**
+	 * Add a line to the table of contents.
+	 * @param phraseLeft The left part of the line
+	 * @param phraseRight The right part of the line
+	 * @param font The line's font
+	 * @param paragraph The paragraph to append the line to
+	 */
+	private void addTocLine(Phrase phraseLeft, Phrase phraseRight, Font font, Paragraph paragraph)
+	{
+		float phraseLeftWidth = ColumnText.getWidth(phraseLeft);
+    float phraseRightWidth = ColumnText.getWidth(phraseRight);
+    float widthRemaining = document.right() - document.left() - phraseRightWidth - phraseLeftWidth;
+    float cw = ColumnText.getWidth(new Phrase(" .", font));
+    paragraph.add(phraseLeft);
+    StringBuilder sb = new StringBuilder();
+    for (int i = 0; i < (widthRemaining / cw) - 4; i++)
+    {
+    	sb.append(" .");
+    }
+    sb.append(" ");
+    paragraph.add(new Phrase(sb.toString(), font));
+    paragraph.add(phraseRight);
+    paragraph.add(Chunk.NEWLINE);
+    paragraph.setAlignment(Paragraph.ALIGN_JUSTIFIED_ALL);
+	}
+
+	/**
+	 * Make the title page of the document.
+	 * @throws DocumentException If something bad happens
+	 */
+	private void makeTitlePage() throws DocumentException
+	{
+		Paragraph p = new Paragraph(title, chapterFont);
+		p.setAlignment(Paragraph.ALIGN_CENTER);
+		//document.add(p);
+		//Subtitle
+		if (subtitle != null)
+		{
+			for (int i = 0; i < 2; i++)
+			{
+				p.add(Chunk.NEWLINE);
+			}	
+			p.add(new Chunk(subtitle, sectionFont));
+		}
+		//Author
+		for (int i = 0; i < 3; i++)
+		{
+			p.add(Chunk.NEWLINE);
+		}
+		p.add(new Chunk(author, sectionFont));
+		//Copyright notice
+		if (copyright != null)
+		{
+			for (int i = 0; i < 2; i++)
+			{
+				p.add(Chunk.NEWLINE);
+			}
+			p.add(new Chunk(copyright, normalFont));		
+		}
+		document.add(p);
+		//Make a new page after the end of the titlepage
+		document.newPage();
+	}
+
+	/**
+	 * Add a new directory to the document.
+	 * @param dir The new directory
+	 */
+	private void addDirectory(File dir)
+	{
+		String packageName;
+		if (dir.equals(sourceDir))
+		{
+			//Root directory
+			packageName = "<default>";
+		}
+		else
+		{
+			//Get the package name
+			File parent = dir.getParentFile();
+			packageName = dir.getName();
+			while (!parent.equals(sourceDir))
+			{
+				packageName = parent.getName() + "." + packageName;
+				parent = parent.getParentFile();
+			}
+		}
+		//Walk through the directory
+		List<File> files = new LinkedList<File>();
+		List<File> dirs = new LinkedList<File>();
+		if (!dir.isDirectory())
+		{
+			throw new IllegalArgumentException("Argument dir must denote a directory!");
+		}
+		for (File child: dir.listFiles())
+		{
+			if (child.isHidden() && !includeHidden)
+			{
+				//Skip hidden files unless required otherwise
+				continue;
+			}
+			if (child.isDirectory())
+			{
+				dirs.add(child);
+			}
+			else
+			{
+				//Get the file extension
+				int lastDotIndex = child.getName().lastIndexOf(".");
+				//if file extension present, check it
+				if (lastDotIndex >= 0)
+				{
+					String extension = child.getName().substring(lastDotIndex + 1);
+					//Skip excluded file extensions
+					if (excludedFileExtensions != null)
+					{
+						if (excludedFileExtensions.contains(extension))
+						{
+							continue;
+						}
+					}
+					//Make sure that the file extension is included
+					if (includedFileExtensions != null)
+					{
+						if (!includedFileExtensions.contains(extension))
+						{
+							continue;
+						}
+					}
+				}
+				files.add(child);
+			}
+		}
+		
+		if (files.size() > 0)
+		{
+			//Create a new chapter, but only if at least one file
+			// exists in the package
+			Paragraph title = new Paragraph(packageName, chapterFont);
+			Chapter chap = new Chapter(title, chapterNumber++);
+			chap.setNumberDepth(0);
+			for (File file: files)
+			{
+				//Add all the files
+				addFile(file, chap);
+			}
+			try
+			{
+				//Add the chapter to the document
+				document.add(chap);
+			} catch (DocumentException e)
+			{
+				e.printStackTrace();
+			}
+		}
+		for (File subDir: dirs)
+		{
+			//Add all subdirectories
+			addDirectory(subDir);
+		}
+	}
+	
+	/**
+	 * Add a new file to the document.
+	 * @param file The new file
+	 * @param packageName The name of the file's package
+	 * @param chapter The chapter to which the file belongs
+	 */
+	private void addFile(File file, Chapter chapter)
+	{
+		Paragraph title = new Paragraph(file.getName(), sectionFont);
+		Section section = chapter.addSection(title);
+		section.setNumberDepth(0);
+		try
+		{
+			BufferedReader reader = new BufferedReader(new FileReader(file));
+			Paragraph para = new Paragraph();
+			LineParser parser = LineParserFactory.getParserForFile(file);
+			parser.setCodeFont(codeFont);
+			parser.setCommentFont(commentFont);
+			parser.setKeywordFont(keywordFont);
+			while (reader.ready())
+			{
+				String line = reader.readLine();
+				if (line.equals("") && reader.ready())
+				{
+					//Blank line => new paragraph
+					section.add(para);
+					para = new Paragraph();
+				}
+				else
+				{
+					//Parse code line
+					parser.parseLine(line, para);
+					para.add(Chunk.NEWLINE);
+				}
+			}
+			section.add(para);
+			section.add(Chunk.NEXTPAGE);
+		} catch (FileNotFoundException e)
+		{
+			e.printStackTrace();
+			return;
+		} catch (IOException e)
+		{
+			e.printStackTrace();
+			return;
+		}
+		
+	}
+	
+	/**
+	 * Setup the fonts used.
+	 *
+	 */
+	private void setupFonts()
+	{
+		chapterFont = new Font(normalFontFamily, (int)(Font.DEFAULTSIZE * 2.5), Font.BOLD);
+		sectionFont = new Font(normalFontFamily, (int)(Font.DEFAULTSIZE * 1.5), Font.BOLDITALIC);
+		codeFont = new Font(codeFontFamily, Font.DEFAULTSIZE, Font.NORMAL);
+		keywordFont = new Font(codeFontFamily, Font.DEFAULTSIZE, Font.BOLD);
+		commentFont = new Font(codeFontFamily, Font.DEFAULTSIZE, Font.ITALIC);
+		normalFont = new Font(normalFontFamily, Font.DEFAULTSIZE, Font.NORMAL);
+	}
+	
+	/**
+	 * A class representing a chapter in the document.
+	 * 
+	 * @author Martin
+	 *
+	 */
+	static class DocChapter
+	{
+		/**
+		 * The start page of this chapter.
+		 */
+		private int startPage;
+		/**
+		 * The title of this chapter.
+		 */
+		private String title;
+		/**
+		 * Sections contained in this chapter.
+		 */
+		private List<DocSection> sections;
+		/**
+		 * Create a new chapter. 
+		 * @param startPage The page this chapter starts on
+		 * @param title The title of this chapter
+		 */
+		public DocChapter(int startPage, String title)
+		{
+			this.startPage = startPage;
+			this.title = title;
+			this.sections = new LinkedList<DocSection>();
+		}
+		/**
+		...
 
[truncated message content] |