--- /dev/null
+/**\r
+ * Copyright winterwell Mathematics Ltd.\r
+ * @author Daniel Winterstein\r
+ * 11 Jan 2007\r
+ */\r
+package winterwell.markdown.editors;\r
+\r
+import org.eclipse.core.runtime.Assert;\r
+import org.eclipse.jface.text.rules.ICharacterScanner;\r
+import org.eclipse.jface.text.rules.IRule;\r
+import org.eclipse.jface.text.rules.IToken;\r
+import org.eclipse.jface.text.rules.MultiLineRule;\r
+import org.eclipse.jface.text.rules.Token;\r
+\r
+/**\r
+ * \r
+ *\r
+ * @author Daniel Winterstein\r
+ */\r
+public class EmphasisRule implements IRule {\r
+ private static char[][] fDelimiters = null;\r
+ private char[] fSequence;\r
+ protected IToken fToken;\r
+\r
+\r
+ public EmphasisRule(String marker, IToken token) {\r
+ assert marker.equals("*") || marker.equals("_") || marker.equals("**")\r
+ || marker.equals("***") || marker.equals("`") || marker.equals("``");\r
+ Assert.isNotNull(token);\r
+ fSequence = marker.toCharArray();\r
+ fToken = token;\r
+ }\r
+ \r
+ // Copied from org.eclipse.jface.text.rules.PatternRule\r
+ protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) {\r
+ for (int i = 1; i < sequence.length; i++) {\r
+ int c = scanner.read();\r
+ if (c == ICharacterScanner.EOF && eofAllowed) {\r
+ return true;\r
+ } else if (c != sequence[i]) {\r
+ // Non-matching character detected, rewind the scanner back to\r
+ // the start.\r
+ // Do not unread the first character.\r
+ for (int j = i; j > 0; j--)\r
+ scanner.unread();\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+\r
+ /*\r
+ * @see IRule#evaluate(ICharacterScanner)\r
+ * \r
+ * @since 2.0\r
+ */\r
+ public IToken evaluate(ICharacterScanner scanner) {\r
+ // Should be connected only on the right side\r
+ scanner.unread();\r
+ boolean sawSpaceBefore = Character.isWhitespace(scanner.read());\r
+ if (!sawSpaceBefore && scanner.getColumn() != 0) {\r
+ return Token.UNDEFINED;\r
+ }\r
+\r
+ int c = scanner.read();\r
+ // Should be connected only on right side\r
+ if (c != fSequence[0] || !sequenceDetected(scanner, fSequence, false)) {\r
+ scanner.unread();\r
+ return Token.UNDEFINED;\r
+ }\r
+ int readCount = fSequence.length;\r
+ if (fDelimiters == null) {\r
+ fDelimiters = scanner.getLegalLineDelimiters();\r
+ }\r
+ // Start sequence detected\r
+ int delimiterFound = 0;\r
+ // Is it a list item marker, or just a floating *?\r
+ if (sawSpaceBefore) {\r
+ boolean after = Character.isWhitespace(scanner.read());\r
+ scanner.unread();\r
+ if (after)\r
+ delimiterFound = 2;\r
+ }\r
+\r
+ while (delimiterFound < 2\r
+ && (c = scanner.read()) != ICharacterScanner.EOF) {\r
+ readCount++;\r
+\r
+ if (!sawSpaceBefore && c == fSequence[0]\r
+ && sequenceDetected(scanner, fSequence, false)) {\r
+ return fToken;\r
+ }\r
+\r
+ int i;\r
+ for (i = 0; i < fDelimiters.length; i++) {\r
+ if (c == fDelimiters[i][0]\r
+ && sequenceDetected(scanner, fDelimiters[i], true)) {\r
+ delimiterFound++;\r
+ break;\r
+ }\r
+ }\r
+ if (i == fDelimiters.length)\r
+ delimiterFound = 0;\r
+ sawSpaceBefore = Character.isWhitespace(c);\r
+ }\r
+ // Reached ICharacterScanner.EOF\r
+ for (; readCount > 0; readCount--)\r
+ scanner.unread();\r
+ return Token.UNDEFINED;\r
+ }\r
+ \r
+}\r