Bug 361916: [nls tooling][quick assist] Suggestions to fine tune quick
assists in Properties File editor
diff --git a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/HTML2TextReaderTester.java b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/HTML2TextReaderTester.java
index cdac1ac..981a140 100644
--- a/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/HTML2TextReaderTester.java
+++ b/org.eclipse.jface.text.tests/src/org/eclipse/jface/text/tests/HTML2TextReaderTester.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2006, 2008 IBM Corporation and others.
+ * Copyright (c) 2006, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -13,13 +13,22 @@
 import java.io.IOException;
 import java.io.Reader;
 import java.io.StringReader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
 
 import junit.framework.Test;
 import junit.framework.TestCase;
 import junit.framework.TestSuite;
 
+import org.eclipse.swt.custom.StyleRange;
+
 import org.eclipse.jface.internal.text.html.HTML2TextReader;
 
+import org.eclipse.jface.text.TextPresentation;
+
 
 public class HTML2TextReaderTester extends TestCase {
 
@@ -35,63 +44,149 @@
 		return new TestSuite(HTML2TextReaderTester.class);
 	}
 
-	private void verify(String input, String expectedOutput) throws IOException{
+	private void verify(String input, String expectedOutput, int styleRangeCount) throws IOException {
 		Reader reader= new StringReader(input);
-		HTML2TextReader htmlReader= new HTML2TextReader(reader, null);
+		TextPresentation textPresentation= new TextPresentation();
+		HTML2TextReader htmlReader= new HTML2TextReader(reader, textPresentation);
 		String result= htmlReader.getString();
 		if (DEBUG)
-			System.out.println("<"+ result +"/>");
+			System.out.println("<" + result + "/>");
 		assertEquals(expectedOutput, result);
+
+		Iterator styleRangeIterator= textPresentation.getAllStyleRangeIterator();
+		List ranges= new ArrayList();
+		while (styleRangeIterator.hasNext()) {
+			ranges.add(styleRangeIterator.next());
+		}
+
+		assertEquals("Incorrect number of style ranges", styleRangeCount, ranges.size());
+
+		Collections.sort(ranges, new Comparator() {
+			public int compare(Object o1, Object o2) {
+				StyleRange range1= (StyleRange)o1;
+				StyleRange range2= (StyleRange)o2;
+				return range1.start - range2.start;
+			}
+		});
+
+		for (int i= 0; i < ranges.size() - 1; i++) {
+			StyleRange range1= (StyleRange)ranges.get(i);
+			StyleRange range2= (StyleRange)ranges.get(i + 1);
+
+			if (range1.start + range1.length > range2.start) {
+				assertTrue("StyleRanges overlap", false);
+			}
+		}
+
 	}
 
 	public void test0() throws IOException{
 		String string= "<code>3<5<code>";
 		String expected= "3<5";
-		verify(string, expected);
+		verify(string, expected, 0);
 	}
 
 	public void test1() throws IOException{
 		String string= "<dl><dt>@author</dt><dd>Foo Bar</dd></dl>";
 		String expected= LD+ "@author"+LD+"\tFoo Bar"+LD;
-		verify(string, expected);
+		verify(string, expected, 1);
 	}
 
 	public void test2() throws IOException{
 		String string= "<code>3>5<code>";
 		String expected= "3>5";
-		verify(string, expected);
+		verify(string, expected, 0);
 	}
 
 	public void test3() throws IOException{
 		String string= "<a href= \"<p>this is only a string - not a tag<p>\">text</a>";
 		String expected= "text";
-		verify(string, expected);
+		verify(string, expected, 0);
 	}
 
 	public void test4() throws IOException{
 		String string= 	"<html><body text=\"#000000\" bgcolor=\"#FFFF88\"><font size=-1><h5>void p.Bb.fes()</h5><p><dl><dt>Parameters:</dt><dd><b>i</b> fred or <code>null</code></dd></dl></font></body></html>";
 		String expected= "void p.Bb.fes()"+ LD + LD + LD+ "Parameters:"+ LD + "\ti fred or null"+LD;
-		verify(string, expected);
+		verify(string, expected, 3);
 	}
 
 	public void test5() throws IOException{
 		String string= "<code>1<2<3<4</code>";
 		String expected= "1<2<3<4";
-		verify(string, expected);
+		verify(string, expected, 0);
 	}
 
 	public void test6() throws IOException{
 		//test for bug 19070
 		String string= "<p>Something.<p>Something more.";
 		String expected= LD + "Something." + LD + "Something more.";
-		verify(string, expected);
+		verify(string, expected, 0);
 	}
 
 	public void testComments() throws Exception {
 		String string= "<!-- begin-user-doc -->no comment<!-- end-user-doc -->";
 		String expected= "no comment";
-		verify(string,expected);
+		verify(string, expected, 0);
 	}
 
+	public void testStyles1() throws IOException {
+		String string= "<b>Hello World</b>";
+		String expected= "Hello World";
+		verify(string, expected, 1);
+	}
+
+	public void testStyles2() throws IOException {
+		String string= "<del>Hello World</del>";
+		String expected= "Hello World";
+		verify(string, expected, 1);
+	}
+
+	public void testStyles3() throws IOException {
+		String string= "<b><del>Hello World</del></b>";
+		String expected= "Hello World";
+		verify(string, expected, 1);
+	}
+
+	public void testStyles4() throws IOException {
+		String string= "<del><b>Hello World</b></del>";
+		String expected= "Hello World";
+		verify(string, expected, 1);
+	}
+
+	public void testStyles5() throws IOException {
+		String string= "<b>This <del> is a </del> test</b>";
+		String expected= "This is a test";
+		verify(string, expected, 3);
+	}
+
+	public void testStyles6() throws IOException {
+		String string= "<del>This <b> is a </b> test</del>";
+		String expected= "This is a test";
+		verify(string, expected, 3);
+	}
+
+	public void testStyles7() throws IOException {
+		String string= "<b>This<del>is a</del>test</b>";
+		String expected= "Thisis atest";
+		verify(string, expected, 3);
+	}
+
+	public void testStyles8() throws IOException {
+		String string= "<del>This<b>is a</b>test</del>";
+		String expected= "Thisis atest";
+		verify(string, expected, 3);
+	}
+
+	public void testStyles9() throws IOException {
+		String string= "<b>This <del>is <b>yet</b> another</del> test</b>";
+		String expected= "This is yet another test";
+		verify(string, expected, 3);
+	}
+
+	public void testStyles10() throws IOException {
+		String string= "<del>This <b>is <del>yet</del> another </b>test</del>";
+		String expected= "This is yet another test";
+		verify(string, expected, 3);
+	}
 }
 
diff --git a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/html/HTML2TextReader.java b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/html/HTML2TextReader.java
index 50d29cb..a39126b 100644
--- a/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/html/HTML2TextReader.java
+++ b/org.eclipse.jface.text/src/org/eclipse/jface/internal/text/html/HTML2TextReader.java
@@ -1,5 +1,5 @@
 /*******************************************************************************
- * Copyright (c) 2000, 2008 IBM Corporation and others.
+ * Copyright (c) 2000, 2011 IBM Corporation and others.
  * All rights reserved. This program and the accompanying materials
  * are made available under the terms of the Eclipse Public License v1.0
  * which accompanies this distribution, and is available at
@@ -43,6 +43,7 @@
 		fgTags.add("br"); //$NON-NLS-1$
 		fgTags.add("br/"); //$NON-NLS-1$
 		fgTags.add("div"); //$NON-NLS-1$
+		fgTags.add("del"); //$NON-NLS-1$
 		fgTags.add("h1"); //$NON-NLS-1$
 		fgTags.add("h2"); //$NON-NLS-1$
 		fgTags.add("h3"); //$NON-NLS-1$
@@ -70,7 +71,9 @@
 	private int fCounter= 0;
 	private TextPresentation fTextPresentation;
 	private int fBold= 0;
-	private int fStartOffset= -1;
+	private int fBoldStartOffset= -1;
+	private int fStrikeout= 0;
+	private int fStrikeoutStartOffset= -1;
 	private boolean fInParagraph= false;
 	private boolean fIsPreformattedText= false;
 	private boolean fIgnore= false;
@@ -95,10 +98,72 @@
 		return c;
 	}
 
+	private void setBold(int offset, int length) {
+		if (fTextPresentation != null && offset >= 0 && length > 0) {
+			fTextPresentation.addStyleRange(new StyleRange(offset, length, null, null, SWT.BOLD));
+		}
+	}
+
+	private void setStrikeout(int offset, int length) {
+		if (fTextPresentation != null && offset >= 0 && length > 0) {
+			StyleRange styleRange= new StyleRange(offset, length, null, null, SWT.NORMAL);
+			styleRange.strikeout= true;
+			fTextPresentation.addStyleRange(styleRange);
+		}
+	}
+
+	private void setBoldAndStrikeOut(int offset, int length) {
+		if (fTextPresentation != null && offset >= 0 && length > 0) {
+			StyleRange styleRange= new StyleRange(offset, length, null, null, SWT.BOLD);
+			styleRange.strikeout= true;
+			fTextPresentation.addStyleRange(styleRange);
+		}
+	}
+
 	protected void startBold() {
-		if (fBold == 0)
-			fStartOffset= fCounter;
-		++ fBold;
+		if (fBold == 0) {
+			fBoldStartOffset= fCounter;
+			if (fStrikeout > 0) {
+				setStrikeout(fStrikeoutStartOffset, fCounter - fStrikeoutStartOffset);
+			}
+		}
+		++fBold;
+	}
+
+	protected void stopBold() {
+		--fBold;
+		if (fBold == 0) {
+			if (fStrikeout == 0) {
+				setBold(fBoldStartOffset, fCounter - fBoldStartOffset);
+			} else {
+				setBoldAndStrikeOut(fBoldStartOffset, fCounter - fBoldStartOffset);
+				fStrikeoutStartOffset= fCounter;
+			}
+			fBoldStartOffset= -1;
+		}
+	}
+
+	protected void startStrikeout() {
+		if (fStrikeout == 0) {
+			fStrikeoutStartOffset= fCounter;
+			if (fBold > 0) {
+				setBold(fBoldStartOffset, fCounter - fBoldStartOffset);
+			}
+		}
+		++fStrikeout;
+	}
+
+	protected void stopStrikeout() {
+		--fStrikeout;
+		if (fStrikeout == 0) {
+			if (fBold == 0) {
+				setStrikeout(fStrikeoutStartOffset, fCounter - fStrikeoutStartOffset);
+			} else {
+				setBoldAndStrikeOut(fStrikeoutStartOffset, fCounter - fStrikeoutStartOffset);
+				fBoldStartOffset= fCounter;
+			}
+			fStrikeoutStartOffset= -1;
+		}
 	}
 
 	protected void startPreformattedText() {
@@ -111,15 +176,6 @@
 		setSkipWhitespace(true);
 	}
 
-	protected void stopBold() {
-		-- fBold;
-		if (fBold == 0) {
-			if (fTextPresentation != null) {
-				fTextPresentation.addStyleRange(new StyleRange(fStartOffset, fCounter - fStartOffset, null, null, SWT.BOLD));
-			}
-			fStartOffset= -1;
-		}
-	}
 
 	/*
 	 * @see org.eclipse.jdt.internal.ui.text.SubstitutionTextReader#computeSubstitution(int)
@@ -171,6 +227,11 @@
 			return EMPTY_STRING;
 		}
 
+		if ("del".equals(html)) { //$NON-NLS-1$
+			startStrikeout();
+			return EMPTY_STRING;
+		}
+
 		if ((html.length() > 1 && html.charAt(0) == 'h' && Character.isDigit(html.charAt(1))) || "dt".equals(html)) { //$NON-NLS-1$
 			startBold();
 			return EMPTY_STRING;
@@ -191,6 +252,11 @@
 			return EMPTY_STRING;
 		}
 
+		if ("/del".equals(html)) { //$NON-NLS-1$
+			stopStrikeout();
+			return EMPTY_STRING;
+		}
+
 		if ("p".equals(html))  { //$NON-NLS-1$
 			fInParagraph= true;
 			return LINE_DELIM;