Index: Components/ArticleView/NSString+TolerantHTML.m
===================================================================
--- Components/ArticleView/NSString+TolerantHTML.m	(revision 3888)
+++ Components/ArticleView/NSString+TolerantHTML.m	(working copy)
@@ -84,6 +84,8 @@
         @"openPre:",@"pre",
 	@"openCode:",@"code",
 	@"openImage:",@"img",
+	@"openComment:", @"!--",
+        @"openXml:", @"?xml",
         nil
     ] retain];
     NSLog(@"opening: %@", openingTagsHandlers);
@@ -98,6 +100,8 @@
         @"stylePop",@"pre",
 	@"stylePop",@"code",
 	@"stylePop",@"img",
+	@"stylePop", @"!--",
+	@"stylePop", @"?xml",
         nil
     ] retain];
     
@@ -440,7 +444,47 @@
     [self stylePush: attributes];
 }
 
+-(void) openComment: (NSDictionary*) aDictionary
+{
+  /*// NOTE: inside <pre> a comment may be allowed to be visible...
+    //       the code chunk below does it
+    NSString *comment;
 
+    if ((comment = [aDictionary objectForKey: @"commentTag"]) != nil)
+    {
+      //[self pushStyleWithFontTrait: NSItalicFontMask];
+      [self foundPlaintext: comment];
+    }
+
+  */
+}
+
+-(void) openXml: (NSDictionary*) aDictionary
+{
+  /*
+  // NOTE: inside <pre> a xml tag may be allowed to be visible...
+    //       the code chunk below does it
+  NSString *xml = [aDictionary objectForKey: @"xmlTag"];
+  NSEnumerator *en;
+  NSString *attrName;
+  NSString *attrValue; 
+
+  if (xml == nil)
+    {
+      xml = @"<?xml ";
+      en = [aDictionary keyEnumerator];
+      while ((attrName = [en nextObject]) != nil)
+	{
+	  attrValue = [aDictionary objectForKey: attrName];
+	  xml = [xml stringByAppendingFormat: @"%@=\"%@\" ", attrName, attrValue];
+	  //[self pushStyleWithFontTrait: NSItalicFontMask];
+	}
+      xml = [xml stringByAppendingString: @"?>"];
+    }
+  [self foundPlaintext: xml];
+  */
+}
+
 // ---------------------------------------------------------------------------------
 //    different fonts
 // ---------------------------------------------------------------------------------
@@ -552,6 +596,17 @@
                 BOOL closing = NO;
                 NSMutableDictionary* attrDict;
                 unichar nextChar;
+		BOOL comment = NO;      // the flag of <!-- ... -->
+		BOOL xml = NO;          // the flag of <?xml ... ?>
+		// The character sets usually used to parse normal tags are different from
+		// the character sets required to parse comments and xmls...
+		// hence these three vars to temporarily store the usual sets for normal tags
+		NSCharacterSet *tc = nil;     // tagClosing 
+		NSCharacterSet *wstc = nil;   // whitespacesAndTagClosing
+		NSCharacterSet *wsrtb = nil;  // whitespacesAndRightTagBrackets
+		unichar charA = '>';          // end of parsing for usual tags
+		unichar charB = '/';          // --*--
+		NSString *tag;                // the whole tag from the start to the end <...>
 
                 // ASSERT: At the beginning of a tag.
                 NSAssert1(ch == '<', @"Beginning of a tag expected, got '%c' instead", ch);
@@ -562,138 +617,222 @@
                 [scanner scanString: @"<" intoString: (NSString**)nil];
 
 		nextChar = [self characterAtIndex: [scanner scanLocation]];
-                if (nextChar == '/') {
+                if (nextChar == '/')
+		  {
 		    [scanner scanString: @"/" intoString: (NSString**)nil];
-                    closing = YES;
-                    opening = NO;
-                } else if (nextChar == '?') {
-		  // <?xml.....?>
-		  [scanner setScanLocation: start]; // return to <
-		  [scanner scanUpToString: @"?>" intoString: &str];
-		  NSAssert(str != nil, @"Malformed '<?'");
-		  [scanner scanString: @"?>" intoString: (NSString**)nil];
-		  continue;
-		} else if (nextChar == '!') {
-		  // <!-- -->
-		  [scanner setScanLocation: start]; // return to <
-		  [scanner scanUpToString: @"-->" intoString: &str];
-		  NSAssert(str != nil, @"Malformed '<!--'");
-		  [scanner scanString: @"-->" intoString: (NSString**)nil];
-		  continue;
-		}
+		    closing = YES;
+		    opening = NO;
+		  }
+		else if (nextChar == '!')
+		  {
+		    // <!-- -->
+		    res = [scanner scanString: @"!--" intoString: &name];
+		    NSAssert(res, @"Malformed start of <!-- ... -->");
+		    // comments are rare so no reason to have static vars for them
+		    tc = tagClosing;                        // temporarily store to restore for the next pass
+		    tagClosing = [NSCharacterSet characterSetWithCharactersInString: @"-"]; // '>' allowed inside comments <!-- ... -->
+		    wstc = whitespacesAndTagClosing;        // temporarily store to restore for the next pass
+		    whitespacesAndTagClosing = [NSCharacterSet characterSetWithCharactersInString: @"- \t\n\r"];
+		    wsrtb = whitespacesAndRightTagBrackets; // temporarily store to restore for the next pass
+		    whitespacesAndRightTagBrackets = whitespacesAndTagClosing; // comments are always closing
 
-                [scanner scanUpToCharactersFromSet: whitespacesAndTagClosing intoString: &name];
-                [scanner scanCharactersFromSet: whitespaces intoString: (NSString**)nil];
+		    charA = '-'; // end of parsing is different for comments
+		    charB = '-'; // bc '>' allowed inside comments <!-- ... -->
+		    closing = YES;
+		    opening = YES;
+		    comment = YES;
+		  }
+		else if (nextChar == '?')
+		  {
+		    // <?xml ?>
+		    res = [scanner scanString: @"?xml" intoString: &name];
+		    NSAssert(res, @"Malformed start of <?xml ... ?>");
+		    // xml is rare so no reason to have a static var for it
+		    tc = tagClosing;                        // temporarily store to restore for the next pass
+		    tagClosing = [NSCharacterSet characterSetWithCharactersInString: @"?>"];
+		    wstc = whitespacesAndTagClosing;        // temporarily store to restore for the next pass
+		    whitespacesAndTagClosing = [NSCharacterSet characterSetWithCharactersInString: @"?> \t\n\r"];
+		    wsrtb = whitespacesAndRightTagBrackets; // temporarily store to restore for the next pass
+		    whitespacesAndRightTagBrackets = whitespacesAndTagClosing; // xml are always closing
 
-                nextChar = [self characterAtIndex: [scanner scanLocation]];
+		    charA = '?'; // end of parsing is different for xml
+		    // charB is the same as for normal tags
+		    closing = YES;
+		    opening = YES;
+		    xml = YES;
+		  }
 
-                while (nextChar != '>' && nextChar != '/') {
-		  if (!pre)
+		if (!comment && !xml)
+		  {
+		    // the tag name of comment or xml is already known
+		    [scanner scanUpToCharactersFromSet: whitespacesAndTagClosing intoString: &name];
+		  }
+		[scanner scanCharactersFromSet: whitespaces intoString: (NSString**)nil];
+
+		nextChar = [self characterAtIndex: [scanner scanLocation]];
+
+		while (nextChar != charA && nextChar != charB) {
+		  if (!comment)
 		    {
-		      // ASSERT: At the beginning of a new attribute
-		      NSString* attrName = nil;
-		      NSString* attrValue = nil;
-                    
-		      [scanner scanUpToString: @"=" intoString: &attrName];
-		      [scanner scanString: @"=" intoString: (NSString**)nil];
+		      if (!pre)
+			{
+			  // ASSERT: At the beginning of a new attribute
+			  NSString* attrName = nil;
+			  NSString* attrValue = nil;
 
-		      if ([scanner scanString: @"\"" intoString: (NSString**)nil] == YES)
-			{
-			  // double quotation marks
-			  [scanner scanUpToString: @"\"" intoString: &attrValue];
-			  [scanner scanString: @"\"" intoString: (NSString**)nil];
-			}
-		      else if ([scanner scanString: @"\'" intoString: (NSString**)nil] == YES)
-			{
-			  // single quotation marks
-			  [scanner scanUpToString: @"\'" intoString: &attrValue];
-			  [scanner scanString: @"\'" intoString: (NSString**)nil];
-			}
-		      else
-			{
-			  [scanner scanUpToCharactersFromSet: whitespacesAndRightTagBrackets
-						  intoString: &attrValue];
-			}
-		      [scanner scanCharactersFromSet: whitespaces intoString: (NSString**)nil];
-		      if (attrName)
-			{
-			  if (attrValue == nil)
+			  [scanner scanUpToString: @"=" intoString: &attrName];
+			  [scanner scanString: @"=" intoString: (NSString**)nil];
+
+			  if ([scanner scanString: @"\"" intoString: (NSString**)nil] == YES)
 			    {
-			      NSLog(@"Value was nil for attribute %@ in tag %@", attrName, name);
-			      [attrDict setObject: [NSNull null] forKey: attrName];
+			      // double quotation marks
+			      [scanner scanUpToString: @"\"" intoString: &attrValue];
+			      [scanner scanString: @"\"" intoString: (NSString**)nil];
 			    }
+			  else if ([scanner scanString: @"\'" intoString: (NSString**)nil] == YES)
+			    {
+			      // single quotation marks
+			      [scanner scanUpToString: @"\'" intoString: &attrValue];
+			      [scanner scanString: @"\'" intoString: (NSString**)nil];
+			    }
 			  else
 			    {
-			      [attrDict setObject: attrValue forKey: attrName];
+			      [scanner scanUpToCharactersFromSet: whitespacesAndRightTagBrackets
+						      intoString: &attrValue];
 			    }
+			  [scanner scanCharactersFromSet: whitespaces intoString: (NSString**)nil];
+			  if (attrName)
+			    {
+			      if (attrValue == nil)
+				{
+				  NSLog(@"Value was nil for attribute %@ in tag %@", attrName, name);
+				  [attrDict setObject: [NSNull null] forKey: attrName];
+				}
+			      else
+				{
+				  [attrDict setObject: attrValue forKey: attrName];
+				}
+			    }
+			  else
+			    {
+			      NSLog(@"Attribute name was nil in tag %@", name);
+			    }
 			}
-		      else
+		      else // pre
 			{
-			  NSLog(@"Attribute name was nil in tag %@", name);
+			  [scanner scanUpToCharactersFromSet: tagClosing intoString: (NSString**)nil];
 			}
 		    }
-		  else
+		  else // comment
 		    {
 		      [scanner scanUpToCharactersFromSet: tagClosing intoString: (NSString**)nil];
+		      // single '-' is allowed inside comments so one can be passed and only the second
+		      // would trigger exiting from the current cycle
+		      res = [scanner scanString: @"-" intoString: (NSString**)nil];
+		      if (!res)
+			{
+			  // missed the end of comment and reached the end of the whole text
+			  NSAssert(NO, @"Possibly malformed or unsupported comment");
+			}
 		    }
-                    
-                    nextChar = [self characterAtIndex: [scanner scanLocation]];
-                }
-                
-                if (nextChar == '/') {
+
+		  nextChar = [self characterAtIndex: [scanner scanLocation]];
+		} // while
+
+		if (nextChar == '/')
+		  {
 		    [scanner scanString: @"/" intoString: (NSString**)nil];
-                    closing = YES;
-                    opening = YES;
-                }
+		    closing = YES;
+		    opening = YES;
+		  }
+		else if (nextChar == '-' || comment)
+		  {
+		    // the second '-' in the '-->'
+		    res = [scanner scanString: @"-" intoString: (NSString**)nil];
+		    NSAssert(res, @"Malformed end of <!-- ... -->");
+		    closing = YES;
+		    opening = YES;
+		  }
+		else if (nextChar == '?' || xml)
+		  {
+		    res = [scanner scanString: @"?" intoString: (NSString**)nil];
+		    NSAssert(res, @"Malformed end of <?xml ... ?>");
+		    closing = YES;
+		    opening = YES;
+		  }
                 
-                [scanner scanString: @">" intoString: (NSString**)nil];
+		[scanner scanString: @">" intoString: (NSString**)nil];
+
 		end = [scanner scanLocation]; // store the after end of tag
 
                 // normalise element name
                 name = [name lowercaseString];
+		//opening ? NSLog(@"%@", name): nil;
 
-                if (opening) {
-		  res = [interpreter foundOpeningTagName: name
-					      attributes: attrDict];
+                if (opening)
+		  {
+		    if (comment)
+		      {
+			tag = [self substringWithRange: NSMakeRange(start, end - start)];
+			[attrDict setObject: tag forKey: @"commentTag"]; // store the content of the comment
+		      }
+		    if (xml && pre)
+		      {
+			tag = [self substringWithRange: NSMakeRange(start, end - start)];
+			[attrDict setObject: tag forKey: @"xmlTag"]; // store the content of the xml if inside pre
+		      }
 
-		  if (pre && !res)
-		    {
-		      // do not eat unknown tags inside <pre>
-		      [interpreter foundPlaintext:
-				     [self substringWithRange: NSMakeRange(start, end - start)]];
-		    }
+		    res = [interpreter foundOpeningTagName: name
+						attributes: attrDict];
 
-		  // TODO: People use <br/> inside <pre>, parse that!
-		  if ([name isEqualToString: @"pre"])
-		    {
-		      NSString* preformattedText;
+		    // NOTE: here comments and xml are eaten inside <pre> bc they are known
+		    if (pre && !res)
+		      {
+			// do not eat unknown tags inside <pre>
+			tag = [self substringWithRange: NSMakeRange(start, end - start)];
+			[interpreter foundPlaintext: tag];
+		      }
 
-		      NSAssert(!pre, @"nested <pre>");
+		    // TODO: People use <br/> inside <pre>, parse that!
+		    if ([name isEqualToString: @"pre"])
+		      {
+			NSString* preformattedText;
 
-		      NSUInteger ret = [scanner scanLocation]; // store the location of <pre>' body start
-		      [scanner scanUpToString: @"</pre" intoString: &preformattedText];
+			NSAssert(!pre, @"nested <pre>");
 
-		      NSAssert(preformattedText != nil, @"No matching closing </pre> tag");
+			NSUInteger ret = [scanner scanLocation]; // store the location of <pre>' body start
+			[scanner scanUpToString: @"</pre" intoString: &preformattedText];
 
-		      [scanner setScanLocation: ret];
-		      pre = YES;
-		    }
-                }
+			NSAssert(preformattedText != nil, @"No matching closing </pre> tag");
+
+			[scanner setScanLocation: ret];
+			pre = YES;
+		      }
+		  } // opening
                 
-                if (closing) {
-		  res = [interpreter foundClosingTagName: name
-					      attributes: attrDict];
-		  if (pre && !res)
-		    {
-		      // do not eat unknown tags inside <pre>
-		      [interpreter foundPlaintext:
-				     [self substringWithRange: NSMakeRange(start, end - start)]];
-		    }
+                if (closing)
+		  {
+		    res = [interpreter foundClosingTagName: name
+						attributes: attrDict];
+		    if (pre && !res)
+		      {
+			// do not eat unknown tags inside <pre>
+			[interpreter foundPlaintext:
+				       [self substringWithRange: NSMakeRange(start, end - start)]];
+		      }
 
 		    if ([name isEqualToString: @"pre"]) {
 		      pre = NO;
 		    }
-                }
+		  }
+
+		// restore the character sets for normal tag parsing
+		if (tc != nil)
+		  tagClosing = tc;
+		if (wstc != nil)
+		  whitespacesAndTagClosing = wstc;
+		if (wsrtb != nil)
+		  whitespacesAndRightTagBrackets = wsrtb;
             }
         }
     }
Index: Resources/Data/HTML-Entities.plist
===================================================================
--- Resources/Data/HTML-Entities.plist	(revision 3888)
+++ Resources/Data/HTML-Entities.plist	(working copy)
@@ -169,6 +169,7 @@
      ocirc = 244;
      oelig = 339;
      ograve = 242;
+     ohm = 8486;
      oline = 8254;
      omega = 969;
      omicron = 959;
