--- source/com/wutka/dtd/Scanner.java.old	2005-08-21 11:16:31.000000000 +0200
+++ source/com/wutka/dtd/Scanner.java	2005-08-21 11:17:50.000000000 +0200
@@ -1,432 +1,432 @@
-package com.wutka.dtd;
-
-import java.io.*;
-import java.util.*;
-
-/** Lexical scanner for DTD's
- *
- * @author Mark Wutka
- * @version $Revision: 1.19 $ $Date: 2002/07/31 00:19:10 $ by $Author: wutka $
- */
-
-class Scanner
-{
-	public static final TokenType LTQUES = new TokenType(0, "LTQUES");
-	public static final TokenType IDENTIFIER = new TokenType(1, "IDENTIFIER");
-	public static final TokenType EQUAL = new TokenType(2, "EQUAL");
-	public static final TokenType LPAREN = new TokenType(3, "LPAREN");
-	public static final TokenType RPAREN = new TokenType(4, "RPAREN");
-	public static final TokenType COMMA = new TokenType(5, "COMMA");
-	public static final TokenType STRING = new TokenType(6, "STRING");
-	public static final TokenType QUESGT = new TokenType(7, "QUESGT");
-	public static final TokenType LTBANG = new TokenType(8, "LTBANG");
-	public static final TokenType GT = new TokenType(9, "GT");
-	public static final TokenType PIPE = new TokenType(10, "PIPE");
-	public static final TokenType QUES = new TokenType(11, "QUES");
-	public static final TokenType PLUS = new TokenType(12, "PLUS");
-	public static final TokenType ASTERISK = new TokenType(13, "ASTERISK");
-	public static final TokenType LT = new TokenType(14, "LT");
-	public static final TokenType EOF = new TokenType(15, "EOF");
-	public static final TokenType COMMENT = new TokenType(16, "COMMENT");
-	public static final TokenType PERCENT = new TokenType(17, "PERCENT");
-	public static final TokenType CONDITIONAL =
-        new TokenType(18, "CONDITIONAL");
-	public static final TokenType ENDCONDITIONAL =
-        new TokenType(19, "ENDCONDITIONAL");
-    public static final TokenType NMTOKEN = new TokenType(20, "NMTOKEN");
-
-    protected class StreamInfo
-    {
-        String      id;
-        Reader      in;
-        int         lineNumber = 1;
-        int         column = 1;
-
-        StreamInfo(String id, Reader in)
-        {
-            this.id = id;
-            this.in = in;
-        }
-    };
-
-    protected StreamInfo in;
-    protected Stack inputStreams;
-	protected Token nextToken;
-	protected int nextChar;
-    protected boolean atEOF;
-    protected boolean trace;
-    protected char[] expandBuffer;
-    protected int expandPos;
-    protected Hashtable entityExpansion;
-    protected EntityExpansion expander;
-
-	public Scanner(Reader inReader, EntityExpansion anExpander)
-	{
-        this(inReader, false, anExpander);
-	}
-
-	public Scanner(Reader inReader, boolean doTrace, EntityExpansion anExpander)
-    {
-        in = new StreamInfo("", inReader);
-        atEOF = false;
-        trace = doTrace;
-        expandBuffer = null;
-        entityExpansion = new Hashtable();
-        expander = anExpander;
-    }
-
-	public Token peek()
-		throws IOException
-	{
-		if (nextToken == null)
-		{
-			nextToken = readNextToken();
-		}
-
-		return nextToken;
-	}
-
-	public Token get()
-		throws IOException
-	{
-		if (nextToken == null)
-		{
-			nextToken = readNextToken();
-		}
-
-		Token retval = nextToken;
-		nextToken = null;
-
-		return retval;
-	}
-
-    protected int readNextChar()
-        throws IOException
-    {
-        int ch = in.in.read();
-
-        if (ch < 0)
-        {
-            if ((inputStreams != null) && (!inputStreams.empty()))
-            {
-                in.in.close();
-                in = (StreamInfo) inputStreams.pop();
-                return readNextChar();
-            }
-        }
-        return ch;
-    }
-
-	protected int peekChar()
-		throws IOException
-	{
-        if (expandBuffer != null)
-        {
-            return (int) expandBuffer[expandPos];
-        }
-
-		if (nextChar == 0)
-		{
-			nextChar = readNextChar();
-            in.column++;
-            if (nextChar == '\n')
-            {
-                in.lineNumber++;
-                in.column=1;
-            }
-		}
-
-		return nextChar;
-	}
-
-	protected int read()
-		throws IOException
-	{
-        if (expandBuffer != null)
-        {
-            int expNextChar = expandBuffer[expandPos++];
-            if (expandPos >= expandBuffer.length)
-            {
-                expandPos = -1;
-                expandBuffer = null;
-            }
-            if (trace)
-            {
-                System.out.print((char) expNextChar);
-            }
-            return expNextChar;
-        }
-		if (nextChar == 0)
-		{
-			peekChar();
-		}
-
-		int retval = nextChar;
-		nextChar = 0;
-
-        if (trace)
-        {
-            System.out.print((char) retval);
-        }
-		return retval;
-	}
-
-    public String getUntil(char stopChar)
-        throws IOException
-    {
-        StringBuffer out = new StringBuffer();
-
-        int ch;
-
-        while ((ch = read()) >= 0)
-        {
-            if (ch == stopChar)
-            {
-                return out.toString();
-            }
-            out.append((char) ch);
-        }
-        return out.toString();
-    }
-
-    public void skipUntil(char stopChar)
-        throws IOException
-    {
-        int ch;
-
-        while ((ch = read()) >= 0)
-        {
-            if (ch == stopChar)
-            {
-                return;
-            }
-        }
-        return;
-    }
-
-	protected Token readNextToken()
-		throws IOException
-	{
-		for (;;)
-		{
-			int ch = read();
-
-			if (ch == '<')
-			{
-				ch = peekChar();
-				if (ch == '!')
-				{
-					read();
-
-                    if (peekChar() == '[')
-                    {
-                        read();
-
-                        return new Token(CONDITIONAL);
-                    }
-
-					if (peekChar() != '-')
-					{
-						return new Token(LTBANG);
-					}
-					else
-					{
-						read();
-						if (peekChar() != '-')
-						{
-                            throw new DTDParseException(getUriId(),
-								"Invalid character sequence <!-"+read(),
-                                getLineNumber(), getColumn());
-						}
-						read();
-
-						StringBuffer buff = new StringBuffer();
-						for (;;)
-						{
-                            if (peekChar() < 0)
-                            {
-                                throw new DTDParseException(getUriId(),
-                                    "Unterminated comment: <!--"+
-                                    buff.toString(),
-                                    getLineNumber(), getColumn());
-                            }
-
-							if (peekChar() != '-')
-							{
-								buff.append((char) read());
-							}
-							else
-							{
-								read();
-                                if (peekChar() < 0)
-                                {
-                                    throw new DTDParseException(getUriId(),
-                                        "Unterminated comment: <!--"+
-                                        buff.toString(),
-                                        getLineNumber(), getColumn());
-                                }
-								if (peekChar() == '-')
-								{
-									read();
-									if (peekChar() != '>')
-									{
-                                        throw new DTDParseException(getUriId(),
-											"Invalid character sequence --"+
-											read(), getLineNumber(), getColumn());
-									}
-									read();
-									return new Token(COMMENT, buff.toString());
-								}
-								else
-								{
-									buff.append('-');
-								}
-							}
-						}
-					}
-				}
-				else if (ch == '?')
-				{
-					read();
-					return new Token(LTQUES);
-				}
-				else
-				{
-					return new Token(LT);
-				}
-			}
-			else if (ch == '?')
-			{
-// Need to treat ?> as two separate tokens because
-// <!ELEMENT blah (foo)?> needs the ? as a QUES, not QUESGT
-/*				ch = peekChar();
-
-				if (ch == '>')
-				{
-					read();
-					return new Token(QUESGT);
-				}
-				else
-				{
-					return new Token(QUES);
-				}*/
-				return new Token(QUES);
-			}
-			else if ((ch == '"') || (ch == '\''))
-			{
-				int quoteChar = ch;
-
-				StringBuffer buff = new StringBuffer();
-				while (peekChar() != quoteChar)
-				{
-					ch = read();
-					if (ch == '\\')
-					{
-						buff.append((char) read());
+package com.wutka.dtd;
+
+import java.io.*;
+import java.util.*;
+
+/** Lexical scanner for DTD's
+ *
+ * @author Mark Wutka
+ * @version $Revision: 1.19 $ $Date: 2002/07/31 00:19:10 $ by $Author: wutka $
+ */
+
+class Scanner
+{
+	public static final TokenType LTQUES = new TokenType(0, "LTQUES");
+	public static final TokenType IDENTIFIER = new TokenType(1, "IDENTIFIER");
+	public static final TokenType EQUAL = new TokenType(2, "EQUAL");
+	public static final TokenType LPAREN = new TokenType(3, "LPAREN");
+	public static final TokenType RPAREN = new TokenType(4, "RPAREN");
+	public static final TokenType COMMA = new TokenType(5, "COMMA");
+	public static final TokenType STRING = new TokenType(6, "STRING");
+	public static final TokenType QUESGT = new TokenType(7, "QUESGT");
+	public static final TokenType LTBANG = new TokenType(8, "LTBANG");
+	public static final TokenType GT = new TokenType(9, "GT");
+	public static final TokenType PIPE = new TokenType(10, "PIPE");
+	public static final TokenType QUES = new TokenType(11, "QUES");
+	public static final TokenType PLUS = new TokenType(12, "PLUS");
+	public static final TokenType ASTERISK = new TokenType(13, "ASTERISK");
+	public static final TokenType LT = new TokenType(14, "LT");
+	public static final TokenType EOF = new TokenType(15, "EOF");
+	public static final TokenType COMMENT = new TokenType(16, "COMMENT");
+	public static final TokenType PERCENT = new TokenType(17, "PERCENT");
+	public static final TokenType CONDITIONAL =
+        new TokenType(18, "CONDITIONAL");
+	public static final TokenType ENDCONDITIONAL =
+        new TokenType(19, "ENDCONDITIONAL");
+    public static final TokenType NMTOKEN = new TokenType(20, "NMTOKEN");
+
+    protected class StreamInfo
+    {
+        String      id;
+        Reader      in;
+        int         lineNumber = 1;
+        int         column = 1;
+
+        StreamInfo(String id, Reader in)
+        {
+            this.id = id;
+            this.in = in;
+        }
+    };
+
+    protected StreamInfo in;
+    protected Stack inputStreams;
+	protected Token nextToken;
+	protected int nextChar;
+    protected boolean atEOF;
+    protected boolean trace;
+    protected char[] expandBuffer;
+    protected int expandPos;
+    protected Hashtable entityExpansion;
+    protected EntityExpansion expander;
+
+	public Scanner(Reader inReader, EntityExpansion anExpander)
+	{
+        this(inReader, false, anExpander);
+	}
+
+	public Scanner(Reader inReader, boolean doTrace, EntityExpansion anExpander)
+    {
+        in = new StreamInfo("", inReader);
+        atEOF = false;
+        trace = doTrace;
+        expandBuffer = null;
+        entityExpansion = new Hashtable();
+        expander = anExpander;
+    }
+
+	public Token peek()
+		throws IOException
+	{
+		if (nextToken == null)
+		{
+			nextToken = readNextToken();
+		}
+
+		return nextToken;
+	}
+
+	public Token get()
+		throws IOException
+	{
+		if (nextToken == null)
+		{
+			nextToken = readNextToken();
+		}
+
+		Token retval = nextToken;
+		nextToken = null;
+
+		return retval;
+	}
+
+    protected int readNextChar()
+        throws IOException
+    {
+        int ch = in.in.read();
+
+        if (ch < 0)
+        {
+            if ((inputStreams != null) && (!inputStreams.empty()))
+            {
+                in.in.close();
+                in = (StreamInfo) inputStreams.pop();
+                return readNextChar();
+            }
+        }
+        return ch;
+    }
+
+	protected int peekChar()
+		throws IOException
+	{
+        if (expandBuffer != null)
+        {
+            return (int) expandBuffer[expandPos];
+        }
+
+		if (nextChar == 0)
+		{
+			nextChar = readNextChar();
+            in.column++;
+            if (nextChar == '\n')
+            {
+                in.lineNumber++;
+                in.column=1;
+            }
+		}
+
+		return nextChar;
+	}
+
+	protected int read()
+		throws IOException
+	{
+        if (expandBuffer != null)
+        {
+            int expNextChar = expandBuffer[expandPos++];
+            if (expandPos >= expandBuffer.length)
+            {
+                expandPos = -1;
+                expandBuffer = null;
+            }
+            if (trace)
+            {
+                System.out.print((char) expNextChar);
+            }
+            return expNextChar;
+        }
+		if (nextChar == 0)
+		{
+			peekChar();
+		}
+
+		int retval = nextChar;
+		nextChar = 0;
+
+        if (trace)
+        {
+            System.out.print((char) retval);
+        }
+		return retval;
+	}
+
+    public String getUntil(char stopChar)
+        throws IOException
+    {
+        StringBuffer out = new StringBuffer();
+
+        int ch;
+
+        while ((ch = read()) >= 0)
+        {
+            if (ch == stopChar)
+            {
+                return out.toString();
+            }
+            out.append((char) ch);
+        }
+        return out.toString();
+    }
+
+    public void skipUntil(char stopChar)
+        throws IOException
+    {
+        int ch;
+
+        while ((ch = read()) >= 0)
+        {
+            if (ch == stopChar)
+            {
+                return;
+            }
+        }
+        return;
+    }
+
+	protected Token readNextToken()
+		throws IOException
+	{
+		for (;;)
+		{
+			int ch = read();
+
+			if (ch == '<')
+			{
+				ch = peekChar();
+				if (ch == '!')
+				{
+					read();
+
+                    if (peekChar() == '[')
+                    {
+                        read();
+
+                        return new Token(CONDITIONAL);
+                    }
+
+					if (peekChar() != '-')
+					{
+						return new Token(LTBANG);
+					}
+					else
+					{
+						read();
+						if (peekChar() != '-')
+						{
+                            throw new DTDParseException(getUriId(),
+								"Invalid character sequence <!-"+read(),
+                                getLineNumber(), getColumn());
+						}
+						read();
+
+						StringBuffer buff = new StringBuffer();
+						for (;;)
+						{
+                            if (peekChar() < 0)
+                            {
+                                throw new DTDParseException(getUriId(),
+                                    "Unterminated comment: <!--"+
+                                    buff.toString(),
+                                    getLineNumber(), getColumn());
+                            }
+
+							if (peekChar() != '-')
+							{
+								buff.append((char) read());
+							}
+							else
+							{
+								read();
+                                if (peekChar() < 0)
+                                {
+                                    throw new DTDParseException(getUriId(),
+                                        "Unterminated comment: <!--"+
+                                        buff.toString(),
+                                        getLineNumber(), getColumn());
+                                }
+								if (peekChar() == '-')
+								{
+									read();
+									if (peekChar() != '>')
+									{
+                                        throw new DTDParseException(getUriId(),
+											"Invalid character sequence --"+
+											read(), getLineNumber(), getColumn());
+									}
+									read();
+									return new Token(COMMENT, buff.toString());
+								}
+								else
+								{
+									buff.append('-');
+								}
+							}
+						}
+					}
+				}
+				else if (ch == '?')
+				{
+					read();
+					return new Token(LTQUES);
+				}
+				else
+				{
+					return new Token(LT);
+				}
+			}
+			else if (ch == '?')
+			{
+// Need to treat ?> as two separate tokens because
+// <!ELEMENT blah (foo)?> needs the ? as a QUES, not QUESGT
+/*				ch = peekChar();
+
+				if (ch == '>')
+				{
+					read();
+					return new Token(QUESGT);
+				}
+				else
+				{
+					return new Token(QUES);
+				}*/
+				return new Token(QUES);
+			}
+			else if ((ch == '"') || (ch == '\''))
+			{
+				int quoteChar = ch;
+
+				StringBuffer buff = new StringBuffer();
+				while (peekChar() != quoteChar)
+				{
+					ch = read();
+					if (ch == '\\')
+					{
+						buff.append((char) read());
 					}
                     else if (ch < 0)
                     {
                         break;  // IF EOF before getting end quote
-                    }
-					else
-					{
-						buff.append((char) ch);
-					}
-				}
-				read();
-				return new Token(STRING, buff.toString());
-			}
-			else if (ch == '(')
-			{
-				return new Token(LPAREN);
-			}
-			else if (ch == ')')
-			{
-				return new Token(RPAREN);
-			}
-			else if (ch == '|')
-			{
-				return new Token(PIPE);
-			}
-			else if (ch == '>')
-			{
-				return new Token(GT);
-			}
-			else if (ch == '=')
-			{
-				return new Token(EQUAL);
-			}
-			else if (ch == '*')
-			{
-				return new Token(ASTERISK);
-			}
-            else if (ch == ']')
-            {
-                if (read() != ']')
-                {
-                    throw new DTDParseException(getUriId(),
-                        "Illegal character in input stream: "+ch,
-                        getLineNumber(), getColumn());
-                }
-                if (read() != '>')
-                {
-                    throw new DTDParseException(getUriId(),
-                        "Illegal character in input stream: "+ch,
-                        getLineNumber(), getColumn());
-                }
-
-                return new Token(ENDCONDITIONAL);
-            }
-			else if (ch == '#')
-			{
-				StringBuffer buff = new StringBuffer();
-				buff.append((char) ch);
-
+                    }
+					else
+					{
+						buff.append((char) ch);
+					}
+				}
+				read();
+				return new Token(STRING, buff.toString());
+			}
+			else if (ch == '(')
+			{
+				return new Token(LPAREN);
+			}
+			else if (ch == ')')
+			{
+				return new Token(RPAREN);
+			}
+			else if (ch == '|')
+			{
+				return new Token(PIPE);
+			}
+			else if (ch == '>')
+			{
+				return new Token(GT);
+			}
+			else if (ch == '=')
+			{
+				return new Token(EQUAL);
+			}
+			else if (ch == '*')
+			{
+				return new Token(ASTERISK);
+			}
+            else if (ch == ']')
+            {
+                if (read() != ']')
+                {
+                    throw new DTDParseException(getUriId(),
+                        "Illegal character in input stream: "+ch,
+                        getLineNumber(), getColumn());
+                }
+                if (read() != '>')
+                {
+                    throw new DTDParseException(getUriId(),
+                        "Illegal character in input stream: "+ch,
+                        getLineNumber(), getColumn());
+                }
+
+                return new Token(ENDCONDITIONAL);
+            }
+			else if (ch == '#')
+			{
+				StringBuffer buff = new StringBuffer();
+				buff.append((char) ch);
+
                 if (isIdentifierChar((char) peekChar()))
                 {
                     buff.append((char) read());
 
-				    while (isNameChar((char) peekChar()))
-				    {
-					    buff.append((char) read());
-				    }
+				    while (isNameChar((char) peekChar()))
+				    {
+					    buff.append((char) read());
+				    }
+                }
+				return new Token(IDENTIFIER, buff.toString());
+			}
+			else if ((ch == '&') || (ch == '%'))
+			{
+                if ((ch == '%') && Character.isWhitespace((char)peekChar()))
+                {
+                    return new Token(PERCENT);
                 }
-				return new Token(IDENTIFIER, buff.toString());
-			}
-			else if ((ch == '&') || (ch == '%'))
-			{
-                if ((ch == '%') && Character.isWhitespace((char)peekChar()))
-                {
-                    return new Token(PERCENT);
-                }
-
-                boolean peRef = (ch == '%');
-
-				StringBuffer buff = new StringBuffer();
-				buff.append((char) ch);
-
+
+                boolean peRef = (ch == '%');
+
+				StringBuffer buff = new StringBuffer();
+				buff.append((char) ch);
+
                 if (isIdentifierChar((char) peekChar()))
                 {
                     buff.append((char) read());
-				    while (isNameChar((char) peekChar()))
-				    {
-					    buff.append((char) read());
-				    }
+				    while (isNameChar((char) peekChar()))
+				    {
+					    buff.append((char) read());
+				    }
                 }
-
-				if (read() != ';')
-				{
-                    throw new DTDParseException(getUriId(),
-                                "Expected ';' after reference "+
-                                buff.toString()+", found '"+ch+"'",
-                                getLineNumber(), getColumn());
-				}
-                buff.append(';');
-
-                if (peRef)
+
+				if (read() != ';')
+				{
+                    throw new DTDParseException(getUriId(),
+                                "Expected ';' after reference "+
+                                buff.toString()+", found '"+ch+"'",
+                                getLineNumber(), getColumn());
+				}
+                buff.append(';');
+
+                if (peRef)
                 {
                     if (expandEntity(buff.toString()))
-                    {
+                    {
                         continue;
                     }
                     else
@@ -434,467 +434,467 @@
                         // MAW: Added version 1.17
                         // If the entity can't be expanded, don't return it, skip it
                         continue;
-                    }
-                }
-				return new Token(IDENTIFIER, buff.toString());
-			}
-			else if (ch == '+')
-			{
-				return new Token(PLUS);
-			}
-			else if (ch == ',')
-			{
-				return new Token(COMMA);
-			}
-			else if (isIdentifierChar((char) ch))
-			{
-				StringBuffer buff = new StringBuffer();
-				buff.append((char) ch);
-
-				while (isNameChar((char) peekChar()))
-				{
-					buff.append((char) read());
-				}
-				return new Token(IDENTIFIER, buff.toString());
-			}
-			else if (isNameChar((char) ch))
-			{
-				StringBuffer buff = new StringBuffer();
-				buff.append((char) ch);
-
-				while (isNameChar((char) peekChar()))
-				{
-					buff.append((char) read());
-				}
-				return new Token(NMTOKEN, buff.toString());
-			}
-			else if (ch < 0)
-			{
-                if (atEOF)
-                {
-                    throw new IOException("Read past EOF");
-                }
-                atEOF = true;
-				return new Token(EOF);
-			}
-			else if (Character.isWhitespace((char) ch))
-			{
-				continue;
-			}
-			else
-			{
-                throw new DTDParseException(getUriId(),
-                                "Illegal character in input stream: "+ch,
-                                getLineNumber(), getColumn());
-			}
-		}
-	}
-
-    public void skipConditional()
-        throws IOException
-    {
-// 070401 MAW: Fix for nested conditionals provided by Noah Fike
-        // BEGIN CHANGE
-        int ch = 0;
-        int nestingDepth = 0; // Add nestingDepth parameter
-
-//    Everything is ignored within an ignored section, except the
-//    sub-section delimiters '<![' and ']]>'. These must be balanced,
-//    but no section keyword is required:
-//    Conditional Section
-//[61] conditionalSect ::=  includeSect | ignoreSect
-//[62] includeSect ::=  '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
-//[63] ignoreSect ::=  '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
-//[64] ignoreSectContents ::=  Ignore ('<![' ignoreSectContents ']]>' Ignore)*
-//[65] Ignore ::=  Char* - (Char* ('<![' | ']]>') Char*)
-
-        for (;;)
-        {
-            if ( ch != ']' )
-            {
-                ch = read();
-            }
-            if (ch == ']')
-            {
-                ch = read();
-                if (ch == ']')
-                {
-                    ch = read();
-                    if (ch == '>')
-                    {
-                        if ( nestingDepth == 0)
-                        {
-                            // The end of the IGNORE conditional section
-                            // has been found.  Break out of for loop.
-                            break;
-                        }
-                        else
-                        {
-                            // We are within an ignoreSectContents section.  Decrement
-                            // the nesting depth to represent that this section has
-                            // been ended.
-                            nestingDepth--;
-                        }
-                    }
-                }
-            }
-            // See if this is the first character of the beginning of a new section.
-            if (ch == '<')
-            {
-                ch = read();
-                if ( ch == '!' )
-                {
-                    ch = read();
-                    if ( ch == '[' )
-                    {
-                        // The beginning of a new ignoreSectContents section
-                        // has been found.  Increment nesting depth.
-                        nestingDepth++;
-                    }
-                }
-            }
-        }
-// END CHANGE
-    }
-
-    public String getUriId() { return(in.id); }
-    public int getLineNumber() { return in.lineNumber; }
-    public int getColumn() { return in.column; }
-
-	public boolean isIdentifierChar(char ch)
-	{
-		if (isLetter(ch) ||
+                    }
+                }
+				return new Token(IDENTIFIER, buff.toString());
+			}
+			else if (ch == '+')
+			{
+				return new Token(PLUS);
+			}
+			else if (ch == ',')
+			{
+				return new Token(COMMA);
+			}
+			else if (isIdentifierChar((char) ch))
+			{
+				StringBuffer buff = new StringBuffer();
+				buff.append((char) ch);
+
+				while (isNameChar((char) peekChar()))
+				{
+					buff.append((char) read());
+				}
+				return new Token(IDENTIFIER, buff.toString());
+			}
+			else if (isNameChar((char) ch))
+			{
+				StringBuffer buff = new StringBuffer();
+				buff.append((char) ch);
+
+				while (isNameChar((char) peekChar()))
+				{
+					buff.append((char) read());
+				}
+				return new Token(NMTOKEN, buff.toString());
+			}
+			else if (ch < 0)
+			{
+                if (atEOF)
+                {
+                    throw new IOException("Read past EOF");
+                }
+                atEOF = true;
+				return new Token(EOF);
+			}
+			else if (Character.isWhitespace((char) ch))
+			{
+				continue;
+			}
+			else
+			{
+                throw new DTDParseException(getUriId(),
+                                "Illegal character in input stream: "+ch,
+                                getLineNumber(), getColumn());
+			}
+		}
+	}
+
+    public void skipConditional()
+        throws IOException
+    {
+// 070401 MAW: Fix for nested conditionals provided by Noah Fike
+        // BEGIN CHANGE
+        int ch = 0;
+        int nestingDepth = 0; // Add nestingDepth parameter
+
+//    Everything is ignored within an ignored section, except the
+//    sub-section delimiters '<![' and ']]>'. These must be balanced,
+//    but no section keyword is required:
+//    Conditional Section
+//[61] conditionalSect ::= includeSect | ignoreSect
+//[62] includeSect ::= '<![' S? 'INCLUDE' S? '[' extSubsetDecl ']]>'
+//[63] ignoreSect ::= '<![' S? 'IGNORE' S? '[' ignoreSectContents* ']]>'
+//[64] ignoreSectContents ::= Ignore ('<![' ignoreSectContents ']]>' Ignore)*
+//[65] Ignore ::= Char* - (Char* ('<![' | ']]>') Char*)
+
+        for (;;)
+        {
+            if ( ch != ']' )
+            {
+                ch = read();
+            }
+            if (ch == ']')
+            {
+                ch = read();
+                if (ch == ']')
+                {
+                    ch = read();
+                    if (ch == '>')
+                    {
+                        if ( nestingDepth == 0)
+                        {
+                            // The end of the IGNORE conditional section
+                            // has been found. Break out of for loop.
+                            break;
+                        }
+                        else
+                        {
+                            // We are within an ignoreSectContents section.  Decrement
+                            // the nesting depth to represent that this section has
+                            // been ended.
+                            nestingDepth--;
+                        }
+                    }
+                }
+            }
+            // See if this is the first character of the beginning of a new section.
+            if (ch == '<')
+            {
+                ch = read();
+                if ( ch == '!' )
+                {
+                    ch = read();
+                    if ( ch == '[' )
+                    {
+                        // The beginning of a new ignoreSectContents section
+                        // has been found. Increment nesting depth.
+                        nestingDepth++;
+                    }
+                }
+            }
+        }
+// END CHANGE
+    }
+
+    public String getUriId() { return(in.id); }
+    public int getLineNumber() { return in.lineNumber; }
+    public int getColumn() { return in.column; }
+
+	public boolean isIdentifierChar(char ch)
+	{
+		if (isLetter(ch) ||
 			(ch == '_') || (ch == ':'))
-		{
-			return true;
-		}
-		return false;
-	}
-
-	public boolean isNameChar(char ch)
-	{
-		if (isLetter(ch) || isDigit(ch) ||
-			(ch == '-') || (ch == '_') || (ch == '.') || (ch == ':')
-			|| isCombiningChar(ch) || isExtender(ch))
-		{
-			return true;
-		}
-		return false;
-	}
-
-    public boolean isLetter(char ch)
-    {
-        return isBaseChar(ch) || isIdeographic(ch);
-    }
-
-    public boolean isBaseChar(char ch)
-    {
-        for (int i=0; i < letterRanges.length; i++)
-        {
-            if (ch < letterRanges[i][0]) return false;
-            if ((ch >= letterRanges[i][0]) &&
-                (ch <= letterRanges[i][1])) return true;
-        }
-        return false;
-    }
-
-    public boolean isIdeographic(char ch)
-    {
-        if (ch < 0x4e00) return false;
-        if ((ch >= 0x4e00) && (ch <= 0x9fa5)) return true;
-        if (ch == 0x3007) return true;
-        if ((ch >= 0x3021) && (ch <= 0x3029)) return true;
-        return false;
-    }
-
-    public boolean isDigit(char ch)
-    {
-        if ((ch >= 0x0030) && (ch <= 0x0039)) return true;
-        if (ch < 0x0660) return false;
-        if ((ch >= 0x0660) && (ch <= 0x0669)) return true;
-        if (ch < 0x06f0) return false;
-        if ((ch >= 0x06f0) && (ch <= 0x06f9)) return true;
-        if (ch < 0x0966) return false;
-        if ((ch >= 0x0966) && (ch <= 0x096f)) return true;
-        if (ch < 0x09e6) return false;
-        if ((ch >= 0x09e6) && (ch <= 0x09ef)) return true;
-        if (ch < 0x0a66) return false;
-        if ((ch >= 0x0a66) && (ch <= 0x0a6f)) return true;
-        if (ch < 0x0ae6) return false;
-        if ((ch >= 0x0ae6) && (ch <= 0x0aef)) return true;
-        if (ch < 0x0b66) return false;
-        if ((ch >= 0x0b66) && (ch <= 0x0b6f)) return true;
-        if (ch < 0x0be7) return false;
-        if ((ch >= 0x0be7) && (ch <= 0x0bef)) return true;
-        if (ch < 0x0c66) return false;
-        if ((ch >= 0x0c66) && (ch <= 0x0c6f)) return true;
-        if (ch < 0x0ce6) return false;
-        if ((ch >= 0x0ce6) && (ch <= 0x0cef)) return true;
-        if (ch < 0x0d66) return false;
-        if ((ch >= 0x0d66) && (ch <= 0x0d6f)) return true;
-        if (ch < 0x0e50) return false;
-        if ((ch >= 0x0e50) && (ch <= 0x0e59)) return true;
-        if (ch < 0x0ed0) return false;
-        if ((ch >= 0x0ed0) && (ch <= 0x0ed9)) return true;
-        if (ch < 0x0f20) return false;
-        if ((ch >= 0x0f20) && (ch <= 0x0f29)) return true;
-        return false;
-    }
-
-	public boolean isCombiningChar(char ch)
-	{
-		if (ch < 0x0300) return false;
-		if ((ch >= 0x0300) && (ch <= 0x0345)) return true;
-		if ((ch >= 0x0360) && (ch <= 0x0361)) return true;
-		if ((ch >= 0x0483) && (ch <= 0x0486)) return true;
-		if ((ch >= 0x0591) && (ch <= 0x05a1)) return true;
-		if ((ch >= 0x05a3) && (ch <= 0x05b9)) return true;
-		if ((ch >= 0x05bb) && (ch <= 0x05bd)) return true;
-		if (ch == 0x05bf) return true;
-		if ((ch >= 0x05c1) && (ch <= 0x05c2)) return true;
-		if (ch == 0x05c4) return true;
-		if ((ch >= 0x064b) && (ch <= 0x0652)) return true;
-		if (ch == 0x0670) return true;
-		if ((ch >= 0x06d6) && (ch <= 0x06dc)) return true;
-		if ((ch >= 0x06dd) && (ch <= 0x06df)) return true;
-		if ((ch >= 0x06e0) && (ch <= 0x06e4)) return true;
-		if ((ch >= 0x06e7) && (ch <= 0x06e8)) return true;
-		if ((ch >= 0x06ea) && (ch <= 0x06ed)) return true;
-		if ((ch >= 0x0901) && (ch <= 0x0903)) return true;
-		if (ch == 0x093c) return true;
-		if ((ch >= 0x093e) && (ch <= 0x094c)) return true;
-		if (ch == 0x094d) return true;
-		if ((ch >= 0x0951) && (ch <= 0x0954)) return true;
-		if ((ch >= 0x0962) && (ch <= 0x0963)) return true;
-		if ((ch >= 0x0981) && (ch <= 0x0983)) return true;
-		if (ch == 0x09bc) return true;
-		if (ch == 0x09be) return true;
-		if (ch == 0x09bf) return true;
-		if ((ch >= 0x09c0) && (ch <= 0x09c4)) return true;
-		if ((ch >= 0x09c7) && (ch <= 0x09c8)) return true;
-		if ((ch >= 0x09cb) && (ch <= 0x09cd)) return true;
-		if (ch == 0x09d7) return true;
-		if ((ch >= 0x09e2) && (ch <= 0x09e3)) return true;
-		if (ch == 0x0a02) return true;
-		if (ch == 0x0a3c) return true;
-		if (ch == 0x0a3e) return true;
-		if (ch == 0x0a3f) return true;
-		if ((ch >= 0x0a40) && (ch <= 0x0a42)) return true;
-		if ((ch >= 0x0a47) && (ch <= 0x0a48)) return true;
-		if ((ch >= 0x0a4b) && (ch <= 0x0a4d)) return true;
-		if ((ch >= 0x0a70) && (ch <= 0x0a71)) return true;
-		if ((ch >= 0x0a81) && (ch <= 0x0a83)) return true;
-		if (ch == 0x0abc) return true;
-		if ((ch >= 0x0abe) && (ch <= 0x0ac5)) return true;
-		if ((ch >= 0x0ac7) && (ch <= 0x0ac9)) return true;
-		if ((ch >= 0x0acb) && (ch <= 0x0acd)) return true;
-		if ((ch >= 0x0b01) && (ch <= 0x0b03)) return true;
-		if (ch == 0x0b3c) return true;
-		if ((ch >= 0x0b3e) && (ch <= 0x0b43)) return true;
-		if ((ch >= 0x0b47) && (ch <= 0x0b48)) return true;
-		if ((ch >= 0x0b4b) && (ch <= 0x0b4d)) return true;
-		if ((ch >= 0x0b56) && (ch <= 0x0b57)) return true;
-		if ((ch >= 0x0b82) && (ch <= 0x0b83)) return true;
-		if ((ch >= 0x0bbe) && (ch <= 0x0bc2)) return true;
-		if ((ch >= 0x0bc6) && (ch <= 0x0bc8)) return true;
-		if ((ch >= 0x0bca) && (ch <= 0x0bcd)) return true;
-		if (ch == 0x0bd7) return true;
-		if ((ch >= 0x0c01) && (ch <= 0x0c03)) return true;
-		if ((ch >= 0x0c3e) && (ch <= 0x0c44)) return true;
-		if ((ch >= 0x0c46) && (ch <= 0x0c48)) return true;
-		if ((ch >= 0x0c4a) && (ch <= 0x0c4d)) return true;
-		if ((ch >= 0x0c55) && (ch <= 0x0c56)) return true;
-		if ((ch >= 0x0c82) && (ch <= 0x0c83)) return true;
-		if ((ch >= 0x0cbe) && (ch <= 0x0cc4)) return true;
-		if ((ch >= 0x0cc6) && (ch <= 0x0cc8)) return true;
-		if ((ch >= 0x0cca) && (ch <= 0x0ccd)) return true;
-		if ((ch >= 0x0cd5) && (ch <= 0x0cd6)) return true;
-		if ((ch >= 0x0d02) && (ch <= 0x0d03)) return true;
-		if ((ch >= 0x0d3e) && (ch <= 0x0d43)) return true;
-		if ((ch >= 0x0d46) && (ch <= 0x0d48)) return true;
-		if ((ch >= 0x0d4a) && (ch <= 0x0d4d)) return true;
-		if (ch == 0x0d57) return true;
-		if (ch == 0x0e31) return true;
-		if ((ch >= 0x0e34) && (ch <= 0x0e3a)) return true;
-		if ((ch >= 0x0e47) && (ch <= 0x0e4e)) return true;
-		if (ch == 0x0eb1) return true;
-		if ((ch >= 0x0eb4) && (ch <= 0x0eb9)) return true;
-		if ((ch >= 0x0ebb) && (ch <= 0x0ebc)) return true;
-		if ((ch >= 0x0ec8) && (ch <= 0x0ecd)) return true;
-		if ((ch >= 0x0f18) && (ch <= 0x0f19)) return true;
-		if (ch == 0x0f35) return true;
-		if (ch == 0x0f37) return true;
-		if (ch == 0x0f39) return true;
-		if (ch == 0x0f3e) return true;
-		if (ch == 0x0f3f) return true;
-		if ((ch >= 0x0f71) && (ch <= 0x0f84)) return true;
-		if ((ch >= 0x0f86) && (ch <= 0x0f8b)) return true;
-		if ((ch >= 0x0f90) && (ch <= 0x0f95)) return true;
-		if (ch == 0x0f97) return true;
-		if ((ch >= 0x0f99) && (ch <= 0x0fad)) return true;
-		if ((ch >= 0x0fb1) && (ch <= 0x0fb7)) return true;
-		if (ch == 0x0fb9) return true;
-		if ((ch >= 0x20d0) && (ch <= 0x20dc)) return true;
-		if (ch == 0x20e1) return true;
-		if ((ch >= 0x302a) && (ch <= 0x302f)) return true;
-		if (ch == 0x3099) return true;
-		if (ch == 0x309a) return true;
-
-		return false;
-	}
-
-	public boolean isExtender(char ch)
-	{
-		if (ch < 0x00b7) return false;
-
-		if ((ch == 0x00b7) || (ch == 0x02d0) || (ch == 0x02d1) ||
-			(ch == 0x0387) || (ch == 0x0640) || (ch == 0x0e46) ||
-			((ch >= 0x3031) && (ch <= 0x3035)) ||
-			((ch >= 0x309d) && (ch <= 0x309e)) ||
-			((ch >= 0x30fc) && (ch <= 0x30fe))) return true;
-
-		return false;
-	}
-
-    public boolean expandEntity(String entityName)
-        throws IOException
-    {
-        String entity = (String) entityExpansion.get(entityName);
-        if (entity != null)
-        {
-            expand(entity.toCharArray());
-            return true;
-        }
-
-        entityName = entityName.substring(1, entityName.length()-1);
-
-        //System.out.println("Trying to expand: "+entityName);
-        DTDEntity realEntity = expander.expandEntity(entityName);
-        if (realEntity != null)
-        {
-            //System.out.println("Expanded: "+entityName);
-            Reader entityIn = realEntity.getReader();
-            if (entityIn != null)
-            {
-                if (inputStreams == null)
-                {
-                    inputStreams = new Stack();
-                }
-
-                inputStreams.push(in);
-                in = new StreamInfo(realEntity.getExternalId(), entityIn);
-
-                return true;
-            }
-        }
-
-        return false;
-    }
-
-    public void expand(char[] expandChars)
-    {
-        if (expandBuffer != null)
-        {
-            int oldCharsLeft = expandBuffer.length - expandPos;
-
-            char[] newExp = new char[oldCharsLeft + expandChars.length];
-            System.arraycopy(expandChars, 0, newExp, 0,
-                expandChars.length);
-            System.arraycopy(expandBuffer, expandPos, newExp,
-                expandChars.length, oldCharsLeft);
-            expandPos = 0;
-            expandBuffer = newExp;
-            if (expandBuffer.length == 0)
-            {
-                expandBuffer = null;
-                expandPos = -1;
-            }
-        }
-        else
-        {
-            expandBuffer = expandChars;
-            expandPos = 0;
-            if (expandBuffer.length == 0)
-            {
-                expandBuffer = null;
-                expandPos = -1;
-            }
-        }
-    }
-
-    public void addEntity(String entityName, String entityValue)
-    {
-        entityExpansion.put("%"+entityName+";", entityValue);
-    }
-
-    public static char letterRanges[][] = {
-		{ 0x0041, 0x005A }, { 0x0061, 0x007A }, { 0x00C0, 0x00D6 },
-		{ 0x00D8, 0x00F6 }, { 0x00F8, 0x00FF }, { 0x0100, 0x0131 },
-		{ 0x0134, 0x013E }, { 0x0141, 0x0148 }, { 0x014A, 0x017E },
-		{ 0x0180, 0x01C3 }, { 0x01CD, 0x01F0 }, { 0x01F4, 0x01F5 },
-		{ 0x01FA, 0x0217 }, { 0x0250, 0x02A8 }, { 0x02BB, 0x02C1 },
-		{ 0x0386, 0x0386 }, { 0x0388, 0x038A }, { 0x038C, 0x038C },
-		{ 0x038E, 0x03A1 }, { 0x03A3, 0x03CE }, { 0x03D0, 0x03D6 },
-		{ 0x03DA, 0x03DA }, { 0x03DC, 0x03DC }, { 0x03DE, 0x03DE },
-		{ 0x03E0, 0x03E0 }, { 0x03E2, 0x03F3 }, { 0x0401, 0x040C },
-		{ 0x040E, 0x044F }, { 0x0451, 0x045C }, { 0x045E, 0x0481 },
-		{ 0x0490, 0x04C4 }, { 0x04C7, 0x04C8 }, { 0x04CB, 0x04CC },
-		{ 0x04D0, 0x04EB }, { 0x04EE, 0x04F5 }, { 0x04F8, 0x04F9 },
-		{ 0x0531, 0x0556 }, { 0x0559, 0x0559 }, { 0x0561, 0x0586 },
-		{ 0x05D0, 0x05EA }, { 0x05F0, 0x05F2 }, { 0x0621, 0x063A },
-		{ 0x0641, 0x064A }, { 0x0671, 0x06B7 }, { 0x06BA, 0x06BE },
-		{ 0x06C0, 0x06CE }, { 0x06D0, 0x06D3 }, { 0x06D5, 0x06D5 },
-		{ 0x06E5, 0x06E6 }, { 0x0905, 0x0939 }, { 0x093D, 0x093D },
-		{ 0x0958, 0x0961 }, { 0x0985, 0x098C }, { 0x098F, 0x0990 },
-		{ 0x0993, 0x09A8 }, { 0x09AA, 0x09B0 }, { 0x09B2, 0x09B2 },
-		{ 0x09B6, 0x09B9 }, { 0x09DC, 0x09DD }, { 0x09DF, 0x09E1 },
-		{ 0x09F0, 0x09F1 }, { 0x0A05, 0x0A0A }, { 0x0A0F, 0x0A10 },
-		{ 0x0A13, 0x0A28 }, { 0x0A2A, 0x0A30 }, { 0x0A32, 0x0A33 },
-		{ 0x0A35, 0x0A36 }, { 0x0A38, 0x0A39 }, { 0x0A59, 0x0A5C },
-		{ 0x0A5E, 0x0A5E }, { 0x0A72, 0x0A74 }, { 0x0A85, 0x0A8B },
-		{ 0x0A8D, 0x0A8D }, { 0x0A8F, 0x0A91 }, { 0x0A93, 0x0AA8 },
-		{ 0x0AAA, 0x0AB0 }, { 0x0AB2, 0x0AB3 }, { 0x0AB5, 0x0AB9 },
-		{ 0x0ABD, 0x0ABD }, { 0x0AE0, 0x0AE0 }, { 0x0B05, 0x0B0C },
-		{ 0x0B0F, 0x0B10 }, { 0x0B13, 0x0B28 }, { 0x0B2A, 0x0B30 },
-		{ 0x0B32, 0x0B33 }, { 0x0B36, 0x0B39 }, { 0x0B3D, 0x0B3D },
-		{ 0x0B5C, 0x0B5D }, { 0x0B5F, 0x0B61 }, { 0x0B85, 0x0B8A },
-		{ 0x0B8E, 0x0B90 }, { 0x0B92, 0x0B95 }, { 0x0B99, 0x0B9A },
-		{ 0x0B9C, 0x0B9C }, { 0x0B9E, 0x0B9F }, { 0x0BA3, 0x0BA4 },
-		{ 0x0BA8, 0x0BAA }, { 0x0BAE, 0x0BB5 }, { 0x0BB7, 0x0BB9 },
-		{ 0x0C05, 0x0C0C }, { 0x0C0E, 0x0C10 }, { 0x0C12, 0x0C28 },
-		{ 0x0C2A, 0x0C33 }, { 0x0C35, 0x0C39 }, { 0x0C60, 0x0C61 },
-		{ 0x0C85, 0x0C8C }, { 0x0C8E, 0x0C90 }, { 0x0C92, 0x0CA8 },
-		{ 0x0CAA, 0x0CB3 }, { 0x0CB5, 0x0CB9 }, { 0x0CDE, 0x0CDE },
-		{ 0x0CE0, 0x0CE1 }, { 0x0D05, 0x0D0C }, { 0x0D0E, 0x0D10 },
-		{ 0x0D12, 0x0D28 }, { 0x0D2A, 0x0D39 }, { 0x0D60, 0x0D61 },
-		{ 0x0E01, 0x0E2E }, { 0x0E30, 0x0E30 }, { 0x0E32, 0x0E33 },
-		{ 0x0E40, 0x0E45 }, { 0x0E81, 0x0E82 }, { 0x0E84, 0x0E84 },
-		{ 0x0E87, 0x0E88 }, { 0x0E8A, 0x0E8A }, { 0x0E8D, 0x0E8D },
-		{ 0x0E94, 0x0E97 }, { 0x0E99, 0x0E9F }, { 0x0EA1, 0x0EA3 },
-		{ 0x0EA5, 0x0EA5 }, { 0x0EA7, 0x0EA7 }, { 0x0EAA, 0x0EAB },
-		{ 0x0EAD, 0x0EAE }, { 0x0EB0, 0x0EB0 }, { 0x0EB2, 0x0EB3 },
-		{ 0x0EBD, 0x0EBD }, { 0x0EC0, 0x0EC4 }, { 0x0F40, 0x0F47 },
-		{ 0x0F49, 0x0F69 }, { 0x10A0, 0x10C5 }, { 0x10D0, 0x10F6 },
-		{ 0x1100, 0x1100 }, { 0x1102, 0x1103 }, { 0x1105, 0x1107 },
-		{ 0x1109, 0x1109 }, { 0x110B, 0x110C }, { 0x110E, 0x1112 },
-		{ 0x113C, 0x113C }, { 0x113E, 0x113E }, { 0x1140, 0x1140 },
-		{ 0x114C, 0x114C }, { 0x114E, 0x114E }, { 0x1150, 0x1150 },
-		{ 0x1154, 0x1155 }, { 0x1159, 0x1159 }, { 0x115F, 0x1161 },
-		{ 0x1163, 0x1163 }, { 0x1165, 0x1165 }, { 0x1167, 0x1167 },
-		{ 0x1169, 0x1169 }, { 0x116D, 0x116E }, { 0x1172, 0x1173 },
-		{ 0x1175, 0x1175 }, { 0x119E, 0x119E }, { 0x11A8, 0x11A8 },
-		{ 0x11AB, 0x11AB }, { 0x11AE, 0x11AF }, { 0x11B7, 0x11B8 },
-		{ 0x11BA, 0x11BA }, { 0x11BC, 0x11C2 }, { 0x11EB, 0x11EB },
-		{ 0x11F0, 0x11F0 }, { 0x11F9, 0x11F9 }, { 0x1E00, 0x1E9B },
-		{ 0x1EA0, 0x1EF9 }, { 0x1F00, 0x1F15 }, { 0x1F18, 0x1F1D },
-		{ 0x1F20, 0x1F45 }, { 0x1F48, 0x1F4D }, { 0x1F50, 0x1F57 },
-		{ 0x1F59, 0x1F59 }, { 0x1F5B, 0x1F5B }, { 0x1F5D, 0x1F5D },
-		{ 0x1F5F, 0x1F7D }, { 0x1F80, 0x1FB4 }, { 0x1FB6, 0x1FBC },
-		{ 0x1FBE, 0x1FBE }, { 0x1FC2, 0x1FC4 }, { 0x1FC6, 0x1FCC },
-		{ 0x1FD0, 0x1FD3 }, { 0x1FD6, 0x1FDB }, { 0x1FE0, 0x1FEC },
-		{ 0x1FF2, 0x1FF4 }, { 0x1FF6, 0x1FFC }, { 0x2126, 0x2126 },
-		{ 0x212A, 0x212B }, { 0x212E, 0x212E }, { 0x2180, 0x2182 },
-		{ 0x3041, 0x3094 }, { 0x30A1, 0x30FA }, { 0x3105, 0x312C },
-		{ 0xAC00, 0xD7A3 }
-    };
-}
+		{
+			return true;
+		}
+		return false;
+	}
+
+	public boolean isNameChar(char ch)
+	{
+		if (isLetter(ch) || isDigit(ch) ||
+			(ch == '-') || (ch == '_') || (ch == '.') || (ch == ':')
+			|| isCombiningChar(ch) || isExtender(ch))
+		{
+			return true;
+		}
+		return false;
+	}
+
+    public boolean isLetter(char ch)
+    {
+        return isBaseChar(ch) || isIdeographic(ch);
+    }
+
+    public boolean isBaseChar(char ch)
+    {
+        for (int i=0; i < letterRanges.length; i++)
+        {
+            if (ch < letterRanges[i][0]) return false;
+            if ((ch >= letterRanges[i][0]) &&
+                (ch <= letterRanges[i][1])) return true;
+        }
+        return false;
+    }
+
+    public boolean isIdeographic(char ch)
+    {
+        if (ch < 0x4e00) return false;
+        if ((ch >= 0x4e00) && (ch <= 0x9fa5)) return true;
+        if (ch == 0x3007) return true;
+        if ((ch >= 0x3021) && (ch <= 0x3029)) return true;
+        return false;
+    }
+
+    public boolean isDigit(char ch)
+    {
+        if ((ch >= 0x0030) && (ch <= 0x0039)) return true;
+        if (ch < 0x0660) return false;
+        if ((ch >= 0x0660) && (ch <= 0x0669)) return true;
+        if (ch < 0x06f0) return false;
+        if ((ch >= 0x06f0) && (ch <= 0x06f9)) return true;
+        if (ch < 0x0966) return false;
+        if ((ch >= 0x0966) && (ch <= 0x096f)) return true;
+        if (ch < 0x09e6) return false;
+        if ((ch >= 0x09e6) && (ch <= 0x09ef)) return true;
+        if (ch < 0x0a66) return false;
+        if ((ch >= 0x0a66) && (ch <= 0x0a6f)) return true;
+        if (ch < 0x0ae6) return false;
+        if ((ch >= 0x0ae6) && (ch <= 0x0aef)) return true;
+        if (ch < 0x0b66) return false;
+        if ((ch >= 0x0b66) && (ch <= 0x0b6f)) return true;
+        if (ch < 0x0be7) return false;
+        if ((ch >= 0x0be7) && (ch <= 0x0bef)) return true;
+        if (ch < 0x0c66) return false;
+        if ((ch >= 0x0c66) && (ch <= 0x0c6f)) return true;
+        if (ch < 0x0ce6) return false;
+        if ((ch >= 0x0ce6) && (ch <= 0x0cef)) return true;
+        if (ch < 0x0d66) return false;
+        if ((ch >= 0x0d66) && (ch <= 0x0d6f)) return true;
+        if (ch < 0x0e50) return false;
+        if ((ch >= 0x0e50) && (ch <= 0x0e59)) return true;
+        if (ch < 0x0ed0) return false;
+        if ((ch >= 0x0ed0) && (ch <= 0x0ed9)) return true;
+        if (ch < 0x0f20) return false;
+        if ((ch >= 0x0f20) && (ch <= 0x0f29)) return true;
+        return false;
+    }
+
+	public boolean isCombiningChar(char ch)
+	{
+		if (ch < 0x0300) return false;
+		if ((ch >= 0x0300) && (ch <= 0x0345)) return true;
+		if ((ch >= 0x0360) && (ch <= 0x0361)) return true;
+		if ((ch >= 0x0483) && (ch <= 0x0486)) return true;
+		if ((ch >= 0x0591) && (ch <= 0x05a1)) return true;
+		if ((ch >= 0x05a3) && (ch <= 0x05b9)) return true;
+		if ((ch >= 0x05bb) && (ch <= 0x05bd)) return true;
+		if (ch == 0x05bf) return true;
+		if ((ch >= 0x05c1) && (ch <= 0x05c2)) return true;
+		if (ch == 0x05c4) return true;
+		if ((ch >= 0x064b) && (ch <= 0x0652)) return true;
+		if (ch == 0x0670) return true;
+		if ((ch >= 0x06d6) && (ch <= 0x06dc)) return true;
+		if ((ch >= 0x06dd) && (ch <= 0x06df)) return true;
+		if ((ch >= 0x06e0) && (ch <= 0x06e4)) return true;
+		if ((ch >= 0x06e7) && (ch <= 0x06e8)) return true;
+		if ((ch >= 0x06ea) && (ch <= 0x06ed)) return true;
+		if ((ch >= 0x0901) && (ch <= 0x0903)) return true;
+		if (ch == 0x093c) return true;
+		if ((ch >= 0x093e) && (ch <= 0x094c)) return true;
+		if (ch == 0x094d) return true;
+		if ((ch >= 0x0951) && (ch <= 0x0954)) return true;
+		if ((ch >= 0x0962) && (ch <= 0x0963)) return true;
+		if ((ch >= 0x0981) && (ch <= 0x0983)) return true;
+		if (ch == 0x09bc) return true;
+		if (ch == 0x09be) return true;
+		if (ch == 0x09bf) return true;
+		if ((ch >= 0x09c0) && (ch <= 0x09c4)) return true;
+		if ((ch >= 0x09c7) && (ch <= 0x09c8)) return true;
+		if ((ch >= 0x09cb) && (ch <= 0x09cd)) return true;
+		if (ch == 0x09d7) return true;
+		if ((ch >= 0x09e2) && (ch <= 0x09e3)) return true;
+		if (ch == 0x0a02) return true;
+		if (ch == 0x0a3c) return true;
+		if (ch == 0x0a3e) return true;
+		if (ch == 0x0a3f) return true;
+		if ((ch >= 0x0a40) && (ch <= 0x0a42)) return true;
+		if ((ch >= 0x0a47) && (ch <= 0x0a48)) return true;
+		if ((ch >= 0x0a4b) && (ch <= 0x0a4d)) return true;
+		if ((ch >= 0x0a70) && (ch <= 0x0a71)) return true;
+		if ((ch >= 0x0a81) && (ch <= 0x0a83)) return true;
+		if (ch == 0x0abc) return true;
+		if ((ch >= 0x0abe) && (ch <= 0x0ac5)) return true;
+		if ((ch >= 0x0ac7) && (ch <= 0x0ac9)) return true;
+		if ((ch >= 0x0acb) && (ch <= 0x0acd)) return true;
+		if ((ch >= 0x0b01) && (ch <= 0x0b03)) return true;
+		if (ch == 0x0b3c) return true;
+		if ((ch >= 0x0b3e) && (ch <= 0x0b43)) return true;
+		if ((ch >= 0x0b47) && (ch <= 0x0b48)) return true;
+		if ((ch >= 0x0b4b) && (ch <= 0x0b4d)) return true;
+		if ((ch >= 0x0b56) && (ch <= 0x0b57)) return true;
+		if ((ch >= 0x0b82) && (ch <= 0x0b83)) return true;
+		if ((ch >= 0x0bbe) && (ch <= 0x0bc2)) return true;
+		if ((ch >= 0x0bc6) && (ch <= 0x0bc8)) return true;
+		if ((ch >= 0x0bca) && (ch <= 0x0bcd)) return true;
+		if (ch == 0x0bd7) return true;
+		if ((ch >= 0x0c01) && (ch <= 0x0c03)) return true;
+		if ((ch >= 0x0c3e) && (ch <= 0x0c44)) return true;
+		if ((ch >= 0x0c46) && (ch <= 0x0c48)) return true;
+		if ((ch >= 0x0c4a) && (ch <= 0x0c4d)) return true;
+		if ((ch >= 0x0c55) && (ch <= 0x0c56)) return true;
+		if ((ch >= 0x0c82) && (ch <= 0x0c83)) return true;
+		if ((ch >= 0x0cbe) && (ch <= 0x0cc4)) return true;
+		if ((ch >= 0x0cc6) && (ch <= 0x0cc8)) return true;
+		if ((ch >= 0x0cca) && (ch <= 0x0ccd)) return true;
+		if ((ch >= 0x0cd5) && (ch <= 0x0cd6)) return true;
+		if ((ch >= 0x0d02) && (ch <= 0x0d03)) return true;
+		if ((ch >= 0x0d3e) && (ch <= 0x0d43)) return true;
+		if ((ch >= 0x0d46) && (ch <= 0x0d48)) return true;
+		if ((ch >= 0x0d4a) && (ch <= 0x0d4d)) return true;
+		if (ch == 0x0d57) return true;
+		if (ch == 0x0e31) return true;
+		if ((ch >= 0x0e34) && (ch <= 0x0e3a)) return true;
+		if ((ch >= 0x0e47) && (ch <= 0x0e4e)) return true;
+		if (ch == 0x0eb1) return true;
+		if ((ch >= 0x0eb4) && (ch <= 0x0eb9)) return true;
+		if ((ch >= 0x0ebb) && (ch <= 0x0ebc)) return true;
+		if ((ch >= 0x0ec8) && (ch <= 0x0ecd)) return true;
+		if ((ch >= 0x0f18) && (ch <= 0x0f19)) return true;
+		if (ch == 0x0f35) return true;
+		if (ch == 0x0f37) return true;
+		if (ch == 0x0f39) return true;
+		if (ch == 0x0f3e) return true;
+		if (ch == 0x0f3f) return true;
+		if ((ch >= 0x0f71) && (ch <= 0x0f84)) return true;
+		if ((ch >= 0x0f86) && (ch <= 0x0f8b)) return true;
+		if ((ch >= 0x0f90) && (ch <= 0x0f95)) return true;
+		if (ch == 0x0f97) return true;
+		if ((ch >= 0x0f99) && (ch <= 0x0fad)) return true;
+		if ((ch >= 0x0fb1) && (ch <= 0x0fb7)) return true;
+		if (ch == 0x0fb9) return true;
+		if ((ch >= 0x20d0) && (ch <= 0x20dc)) return true;
+		if (ch == 0x20e1) return true;
+		if ((ch >= 0x302a) && (ch <= 0x302f)) return true;
+		if (ch == 0x3099) return true;
+		if (ch == 0x309a) return true;
+
+		return false;
+	}
+
+	public boolean isExtender(char ch)
+	{
+		if (ch < 0x00b7) return false;
+
+		if ((ch == 0x00b7) || (ch == 0x02d0) || (ch == 0x02d1) ||
+			(ch == 0x0387) || (ch == 0x0640) || (ch == 0x0e46) ||
+			((ch >= 0x3031) && (ch <= 0x3035)) ||
+			((ch >= 0x309d) && (ch <= 0x309e)) ||
+			((ch >= 0x30fc) && (ch <= 0x30fe))) return true;
+
+		return false;
+	}
+
+    public boolean expandEntity(String entityName)
+        throws IOException
+    {
+        String entity = (String) entityExpansion.get(entityName);
+        if (entity != null)
+        {
+            expand(entity.toCharArray());
+            return true;
+        }
+
+        entityName = entityName.substring(1, entityName.length()-1);
+
+        //System.out.println("Trying to expand: "+entityName);
+        DTDEntity realEntity = expander.expandEntity(entityName);
+        if (realEntity != null)
+        {
+            //System.out.println("Expanded: "+entityName);
+            Reader entityIn = realEntity.getReader();
+            if (entityIn != null)
+            {
+                if (inputStreams == null)
+                {
+                    inputStreams = new Stack();
+                }
+
+                inputStreams.push(in);
+                in = new StreamInfo(realEntity.getExternalId(), entityIn);
+
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    public void expand(char[] expandChars)
+    {
+        if (expandBuffer != null)
+        {
+            int oldCharsLeft = expandBuffer.length - expandPos;
+
+            char[] newExp = new char[oldCharsLeft + expandChars.length];
+            System.arraycopy(expandChars, 0, newExp, 0,
+                expandChars.length);
+            System.arraycopy(expandBuffer, expandPos, newExp,
+                expandChars.length, oldCharsLeft);
+            expandPos = 0;
+            expandBuffer = newExp;
+            if (expandBuffer.length == 0)
+            {
+                expandBuffer = null;
+                expandPos = -1;
+            }
+        }
+        else
+        {
+            expandBuffer = expandChars;
+            expandPos = 0;
+            if (expandBuffer.length == 0)
+            {
+                expandBuffer = null;
+                expandPos = -1;
+            }
+        }
+    }
+
+    public void addEntity(String entityName, String entityValue)
+    {
+        entityExpansion.put("%"+entityName+";", entityValue);
+    }
+
+    public static char letterRanges[][] = {
+		{ 0x0041, 0x005A }, { 0x0061, 0x007A }, { 0x00C0, 0x00D6 },
+		{ 0x00D8, 0x00F6 }, { 0x00F8, 0x00FF }, { 0x0100, 0x0131 },
+		{ 0x0134, 0x013E }, { 0x0141, 0x0148 }, { 0x014A, 0x017E },
+		{ 0x0180, 0x01C3 }, { 0x01CD, 0x01F0 }, { 0x01F4, 0x01F5 },
+		{ 0x01FA, 0x0217 }, { 0x0250, 0x02A8 }, { 0x02BB, 0x02C1 },
+		{ 0x0386, 0x0386 }, { 0x0388, 0x038A }, { 0x038C, 0x038C },
+		{ 0x038E, 0x03A1 }, { 0x03A3, 0x03CE }, { 0x03D0, 0x03D6 },
+		{ 0x03DA, 0x03DA }, { 0x03DC, 0x03DC }, { 0x03DE, 0x03DE },
+		{ 0x03E0, 0x03E0 }, { 0x03E2, 0x03F3 }, { 0x0401, 0x040C },
+		{ 0x040E, 0x044F }, { 0x0451, 0x045C }, { 0x045E, 0x0481 },
+		{ 0x0490, 0x04C4 }, { 0x04C7, 0x04C8 }, { 0x04CB, 0x04CC },
+		{ 0x04D0, 0x04EB }, { 0x04EE, 0x04F5 }, { 0x04F8, 0x04F9 },
+		{ 0x0531, 0x0556 }, { 0x0559, 0x0559 }, { 0x0561, 0x0586 },
+		{ 0x05D0, 0x05EA }, { 0x05F0, 0x05F2 }, { 0x0621, 0x063A },
+		{ 0x0641, 0x064A }, { 0x0671, 0x06B7 }, { 0x06BA, 0x06BE },
+		{ 0x06C0, 0x06CE }, { 0x06D0, 0x06D3 }, { 0x06D5, 0x06D5 },
+		{ 0x06E5, 0x06E6 }, { 0x0905, 0x0939 }, { 0x093D, 0x093D },
+		{ 0x0958, 0x0961 }, { 0x0985, 0x098C }, { 0x098F, 0x0990 },
+		{ 0x0993, 0x09A8 }, { 0x09AA, 0x09B0 }, { 0x09B2, 0x09B2 },
+		{ 0x09B6, 0x09B9 }, { 0x09DC, 0x09DD }, { 0x09DF, 0x09E1 },
+		{ 0x09F0, 0x09F1 }, { 0x0A05, 0x0A0A }, { 0x0A0F, 0x0A10 },
+		{ 0x0A13, 0x0A28 }, { 0x0A2A, 0x0A30 }, { 0x0A32, 0x0A33 },
+		{ 0x0A35, 0x0A36 }, { 0x0A38, 0x0A39 }, { 0x0A59, 0x0A5C },
+		{ 0x0A5E, 0x0A5E }, { 0x0A72, 0x0A74 }, { 0x0A85, 0x0A8B },
+		{ 0x0A8D, 0x0A8D }, { 0x0A8F, 0x0A91 }, { 0x0A93, 0x0AA8 },
+		{ 0x0AAA, 0x0AB0 }, { 0x0AB2, 0x0AB3 }, { 0x0AB5, 0x0AB9 },
+		{ 0x0ABD, 0x0ABD }, { 0x0AE0, 0x0AE0 }, { 0x0B05, 0x0B0C },
+		{ 0x0B0F, 0x0B10 }, { 0x0B13, 0x0B28 }, { 0x0B2A, 0x0B30 },
+		{ 0x0B32, 0x0B33 }, { 0x0B36, 0x0B39 }, { 0x0B3D, 0x0B3D },
+		{ 0x0B5C, 0x0B5D }, { 0x0B5F, 0x0B61 }, { 0x0B85, 0x0B8A },
+		{ 0x0B8E, 0x0B90 }, { 0x0B92, 0x0B95 }, { 0x0B99, 0x0B9A },
+		{ 0x0B9C, 0x0B9C }, { 0x0B9E, 0x0B9F }, { 0x0BA3, 0x0BA4 },
+		{ 0x0BA8, 0x0BAA }, { 0x0BAE, 0x0BB5 }, { 0x0BB7, 0x0BB9 },
+		{ 0x0C05, 0x0C0C }, { 0x0C0E, 0x0C10 }, { 0x0C12, 0x0C28 },
+		{ 0x0C2A, 0x0C33 }, { 0x0C35, 0x0C39 }, { 0x0C60, 0x0C61 },
+		{ 0x0C85, 0x0C8C }, { 0x0C8E, 0x0C90 }, { 0x0C92, 0x0CA8 },
+		{ 0x0CAA, 0x0CB3 }, { 0x0CB5, 0x0CB9 }, { 0x0CDE, 0x0CDE },
+		{ 0x0CE0, 0x0CE1 }, { 0x0D05, 0x0D0C }, { 0x0D0E, 0x0D10 },
+		{ 0x0D12, 0x0D28 }, { 0x0D2A, 0x0D39 }, { 0x0D60, 0x0D61 },
+		{ 0x0E01, 0x0E2E }, { 0x0E30, 0x0E30 }, { 0x0E32, 0x0E33 },
+		{ 0x0E40, 0x0E45 }, { 0x0E81, 0x0E82 }, { 0x0E84, 0x0E84 },
+		{ 0x0E87, 0x0E88 }, { 0x0E8A, 0x0E8A }, { 0x0E8D, 0x0E8D },
+		{ 0x0E94, 0x0E97 }, { 0x0E99, 0x0E9F }, { 0x0EA1, 0x0EA3 },
+		{ 0x0EA5, 0x0EA5 }, { 0x0EA7, 0x0EA7 }, { 0x0EAA, 0x0EAB },
+		{ 0x0EAD, 0x0EAE }, { 0x0EB0, 0x0EB0 }, { 0x0EB2, 0x0EB3 },
+		{ 0x0EBD, 0x0EBD }, { 0x0EC0, 0x0EC4 }, { 0x0F40, 0x0F47 },
+		{ 0x0F49, 0x0F69 }, { 0x10A0, 0x10C5 }, { 0x10D0, 0x10F6 },
+		{ 0x1100, 0x1100 }, { 0x1102, 0x1103 }, { 0x1105, 0x1107 },
+		{ 0x1109, 0x1109 }, { 0x110B, 0x110C }, { 0x110E, 0x1112 },
+		{ 0x113C, 0x113C }, { 0x113E, 0x113E }, { 0x1140, 0x1140 },
+		{ 0x114C, 0x114C }, { 0x114E, 0x114E }, { 0x1150, 0x1150 },
+		{ 0x1154, 0x1155 }, { 0x1159, 0x1159 }, { 0x115F, 0x1161 },
+		{ 0x1163, 0x1163 }, { 0x1165, 0x1165 }, { 0x1167, 0x1167 },
+		{ 0x1169, 0x1169 }, { 0x116D, 0x116E }, { 0x1172, 0x1173 },
+		{ 0x1175, 0x1175 }, { 0x119E, 0x119E }, { 0x11A8, 0x11A8 },
+		{ 0x11AB, 0x11AB }, { 0x11AE, 0x11AF }, { 0x11B7, 0x11B8 },
+		{ 0x11BA, 0x11BA }, { 0x11BC, 0x11C2 }, { 0x11EB, 0x11EB },
+		{ 0x11F0, 0x11F0 }, { 0x11F9, 0x11F9 }, { 0x1E00, 0x1E9B },
+		{ 0x1EA0, 0x1EF9 }, { 0x1F00, 0x1F15 }, { 0x1F18, 0x1F1D },
+		{ 0x1F20, 0x1F45 }, { 0x1F48, 0x1F4D }, { 0x1F50, 0x1F57 },
+		{ 0x1F59, 0x1F59 }, { 0x1F5B, 0x1F5B }, { 0x1F5D, 0x1F5D },
+		{ 0x1F5F, 0x1F7D }, { 0x1F80, 0x1FB4 }, { 0x1FB6, 0x1FBC },
+		{ 0x1FBE, 0x1FBE }, { 0x1FC2, 0x1FC4 }, { 0x1FC6, 0x1FCC },
+		{ 0x1FD0, 0x1FD3 }, { 0x1FD6, 0x1FDB }, { 0x1FE0, 0x1FEC },
+		{ 0x1FF2, 0x1FF4 }, { 0x1FF6, 0x1FFC }, { 0x2126, 0x2126 },
+		{ 0x212A, 0x212B }, { 0x212E, 0x212E }, { 0x2180, 0x2182 },
+		{ 0x3041, 0x3094 }, { 0x30A1, 0x30FA }, { 0x3105, 0x312C },
+		{ 0xAC00, 0xD7A3 }
+    };
+}
