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