/**
* Copyright winterwell Mathematics Ltd.
* @author Daniel Winterstein
* 11 Jan 2007
*/
package winterwell.markdown.editors;
import org.eclipse.jface.text.rules.ICharacterScanner;
import org.eclipse.jface.text.rules.IToken;
import org.eclipse.jface.text.rules.Token;
import org.eclipse.jface.text.rules.IRule;
import org.eclipse.core.runtime.Assert;
/**
*
*
* @author Amir Pakdel
*/
public class LinkRule implements IRule {
private static char[][] fDelimiters = null;
protected IToken fToken;
public LinkRule(IToken token) {
Assert.isNotNull(token);
fToken= token;
}
/*
* @see IPredicateRule#getSuccessToken()
* @since 2.0
*/
public IToken getSuccessToken() {
return fToken;
}
// 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.
scanner.unread();
for (int j= i-1; j > 0; j--)
scanner.unread();
return false;
}
}
return true;
}
/*
* @see IRule#evaluate(ICharacterScanner)
* @since 2.0
*/
public IToken evaluate(ICharacterScanner scanner) {
int c;
if ((c = scanner.read()) != '[') {
if ((c != 'h' || ( !sequenceDetected(scanner, "http://".toCharArray(), false) && !sequenceDetected(scanner, "https://".toCharArray(), false) ))
&& (c != 'f' || !sequenceDetected(scanner, "ftp://".toCharArray(), false)) ) {
// Not even a non-standard link
scanner.unread();
return Token.UNDEFINED;
}
//+ preventing NPE (Non-standard link should not be below as comment above suggests) by Paul Verest
if (fDelimiters == null) {
scanner.unread();
return Token.UNDEFINED;
}
// Non-standard link
while ((c = scanner.read()) != ICharacterScanner.EOF && !Character.isWhitespace(c)) {
for (int i = 0; i < fDelimiters.length; i++) {
if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) {
return fToken;
}
}
}
return fToken;
}
if (fDelimiters == null) {
fDelimiters = scanner.getLegalLineDelimiters();
}
int readCount = 1;
// Find '](' and then find ')'
boolean sequenceFound = false;
int delimiterFound = 0;
while ((c = scanner.read()) != ICharacterScanner.EOF && delimiterFound < 2) {
readCount++;
if ( !sequenceFound && c == ']') {
c = scanner.read();
if (c == '(') {
readCount++;
sequenceFound = true;
} else {
scanner.unread();
}
} else if (c == ')') { // '](' is already found
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;
}
for (; readCount > 0; readCount--)
scanner.unread();
return Token.UNDEFINED;
}
}