Revision: 609
Author: allain.lalonde
Date: Tue Jul 28 21:35:50 2009
Log: Made PHtml not use regular expressions for parsing HTML3.2 since it  
really couldn't handle malformed HTML at all. At least now there's a  
passing attempt.
http://code.google.com/p/piccolo2d/source/detail?r=609

Added:
   
/piccolo2d.java/branches/phtml/core/src/test/java/edu/umd/cs/piccolo/nodes/PHtmlTest.java
Modified:
   
/piccolo2d.java/branches/phtml/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtml.java

=======================================
--- /dev/null
+++  
/piccolo2d.java/branches/phtml/core/src/test/java/edu/umd/cs/piccolo/nodes/PHtmlTest.java
        
Tue Jul 28 21:35:50 2009
@@ -0,0 +1,52 @@
+package edu.umd.cs.piccolo.nodes;
+
+import java.awt.geom.Point2D;
+
+import junit.framework.TestCase;
+import edu.umd.cs.piccolo.util.PBounds;
+
+public class PHtmlTest extends TestCase {
+
+    public void testGetClickedAddressReturnsSingleQuotedAddress() {
+        PHtml html = new PHtml("<a  
href='http://www.testing.com'>testing</a>");
+        html.setBounds(new PBounds(0, 0, 100, 100));
+        assertEquals("http://www.testing.com";, html.getClickedAddress(new  
Point2D.Double(5,5)));
+    }
+
+    public void testGetClickedAddressReturnsDoubleQuotedAddress() {
+        PHtml html = new PHtml("<a  
href=\"http://www.testing.com\";>testing</a>");
+        html.setBounds(new PBounds(0, 0, 100, 100));
+        assertEquals("http://www.testing.com";, html.getClickedAddress(new  
Point2D.Double(5,5)));
+    }
+
+    public void testBracketsAreValidInHrefs() {
+        PHtml html = new PHtml("<a href='a>b'>testing</a>");
+        html.setBounds(new PBounds(0, 0, 100, 100));
+        assertEquals("a>b", html.getClickedAddress(new  
Point2D.Double(5,5)));
+    }
+
+    public void testGetClickedAddressReturnsNullWhenInvalid() {
+        PHtml html = new PHtml("<a ='a>b'>testing</a>");
+        html.setBounds(new PBounds(0, 0, 100, 100));
+        assertNull(html.getClickedAddress(new Point2D.Double(5,5)));
+    }
+
+    public void testGetClickedAddressReturnsHrefWhenMissingEndAnchorTag() {
+        PHtml html = new PHtml("<a href='testing.com'>testing");
+        html.setBounds(new PBounds(0, 0, 100, 100));
+        assertEquals("testing.com", html.getClickedAddress(new  
Point2D.Double(5,5)));
+    }
+
+    public void testHandlesTricksyTitles() {
+        PHtml html = new PHtml("<a href=\"where to go\" title=\"this is  
not the href='gotcha!' \">testing</a>");
+        html.setBounds(new PBounds(0, 0, 100, 100));
+        assertEquals("where to go", html.getClickedAddress(new  
Point2D.Double(5,5)));
+    }
+
+    public void testHandlesHrefWithoutQuotes() {
+        PHtml html = new PHtml("<a href=testing.com>testing</a>");
+        html.setBounds(new PBounds(0, 0, 100, 100));
+        assertEquals("testing.com", html.getClickedAddress(new  
Point2D.Double(5,5)));
+    }
+
+}
=======================================
---  
/piccolo2d.java/branches/phtml/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtml.java
    
Tue Jul 28 14:37:17 2009
+++  
/piccolo2d.java/branches/phtml/core/src/main/java/edu/umd/cs/piccolo/nodes/PHtml.java
    
Tue Jul 28 21:35:50 2009
@@ -61,12 +61,6 @@

      private static final long serialVersionUID = 1L;

-    // FIXME: imagine <img alt="2>1" src="here comes the meat" />
-    private static final Pattern tagPattern = Pattern.compile("</?[^>]+>");
-    // FIXME: imagine <a href="where to go"
-    // title="this is not the href='gotcha!' " />
-    private static final Pattern linkPattern =  
Pattern.compile("<a .*href=(\\\"([^\\\"]*)\\\"|\\\'([^\\\"]*)\\\')");
-
      private static final Font DEFAULT_FONT = new JTextField().getFont();
      private static final Color DEFAULT_HTML_COLOR = Color.BLACK;

@@ -253,32 +247,103 @@
      public String getClickedAddress(final Point2D clickedPoint) {
          int position = pointToModelIndex(clickedPoint);

-        final Matcher tagMatcher = tagPattern.matcher(htmlLabel.getText());
+        String html = htmlLabel.getText();

          String address = null;

-        while (tagMatcher.find()) {
-            if (position <= tagMatcher.start()) {
+        int currentPos = 0;
+        while (currentPos < html.length()) {
+            if (html.charAt(currentPos) != '<') {
+                currentPos++;
+            }
+            else if (position < currentPos) {
                  break;
              }
-            position += tagMatcher.end() - tagMatcher.start();
-
-            final String tag = tagMatcher.group().toLowerCase();
-            if ("</a>".equals(tag)) {
-                address = null;
-            }
-            else {
-                final Matcher linkMatcher = linkPattern.matcher(tag);
-                if (linkMatcher.find()) {
-                    address = linkMatcher.group(2);
-                    if (address == null) {
-                        address = linkMatcher.group(3);
-                    }
+            else {
+                int tagStart = currentPos;
+                int tagEnd = findTagEnd(html, currentPos);
+
+                currentPos = tagEnd + 1;
+
+                String tag = html.substring(tagStart, tagEnd);
+
+                position += tag.length();
+
+                if ("</a>".equals(tag)) {
+                    address = null;
+                }
+                else if (tag.startsWith("<a ")) {
+                    address = extractHref(tag);
+                }
+            }
+        }
+
+        return address;
+    }
+
+    private String extractHref(String tag) {
+        int currentPos = 0;
+
+        String href = null;
+        int tagLength = tag.length();
+
+        while (currentPos < tag.length() - 1) {
+            currentPos++;
+            if (tag.charAt(currentPos) != '=') {
+                currentPos++;
+            }
+            else if (currentPos > 4 && "  
href".equals(tag.substring(currentPos - 5, currentPos))) {
+                currentPos++;
+                if (tag.charAt(currentPos) == '\"') {
+                    int startHref = currentPos + 1;
+                    if (currentPos < tagLength) {
+                        do {
+                            ++currentPos;
+                        } while (currentPos < tagLength &&  
tag.charAt(currentPos) != '\"');
+                    }
+                    return tag.substring(startHref, currentPos);
+                }
+                else if (currentPos < tagLength && tag.charAt(currentPos)  
== '\'') {
+                    int startHref = currentPos + 1;
+                    if (currentPos < tagLength) {
+                        do {
+                            ++currentPos;
+                        } while (currentPos < tagLength &&  
tag.charAt(currentPos) != '\'');
+                    }
+                    return tag.substring(startHref, currentPos);
+                }
+                else {
+                    int startHref = currentPos;
+
+                    if (currentPos < tagLength) {
+                        do {
+                            currentPos++;
+                        } while (currentPos < tagLength &&  
tag.charAt(currentPos) != ' '
+                                && tag.charAt(currentPos) != '>');
+                    }
+                    return tag.substring(startHref, currentPos);
                  }
              }
          }
-
-        return address;
+        return href;
+    }
+
+    private int findTagEnd(String html, final int startPos) {
+        int currentPos = startPos;
+
+        while (html.charAt(currentPos) != '>') {
+            if (html.charAt(currentPos) == '\"') {
+                while (html.charAt(++currentPos) != '\"')
+                    ;
+            }
+            else if (html.charAt(currentPos) == '\'') {
+                while (html.charAt(++currentPos) != '\'')
+                    ;
+            }
+            currentPos++;
+        }
+
+        return currentPos + 1;
      }

      private int pointToModelIndex(final Point2D clickedPoint) {

--~--~---------~--~----~------------~-------~--~----~
Piccolo2D Developers Group: http://groups.google.com/group/piccolo2d-dev?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to