Tycho compilation changes for SVN version also.
[simantics/platform.git] / bundles / winterwell.markdown / src / winterwell / markdown / editors / LinkRule.java
1 /**
2  * Copyright winterwell Mathematics Ltd.
3  * @author Daniel Winterstein
4  * 11 Jan 2007
5  */
6 package winterwell.markdown.editors;
7
8 import org.eclipse.jface.text.rules.ICharacterScanner;
9 import org.eclipse.jface.text.rules.IToken;
10 import org.eclipse.jface.text.rules.Token;
11 import org.eclipse.jface.text.rules.IRule;
12 import org.eclipse.core.runtime.Assert;
13
14 /**
15  * 
16  *
17  * @author Amir Pakdel
18  */
19 public class LinkRule implements IRule {
20         private static char[][] fDelimiters = null;
21         protected IToken fToken;
22
23         public LinkRule(IToken token) {
24                 Assert.isNotNull(token);
25                 fToken= token;
26         }
27         
28         /*
29          * @see IPredicateRule#getSuccessToken()
30          * @since 2.0
31          */
32         public IToken getSuccessToken() {
33                 return fToken;
34         }
35
36
37         // Copied from org.eclipse.jface.text.rules.PatternRule
38         protected boolean sequenceDetected(ICharacterScanner scanner, char[] sequence, boolean eofAllowed) {
39                 for (int i= 1; i < sequence.length; i++) {
40                         int c= scanner.read();
41                         if (c == ICharacterScanner.EOF && eofAllowed) {
42                                 return true;
43                         } else if (c != sequence[i]) {
44                                 // Non-matching character detected, rewind the scanner back to the start.
45                                 // Do not unread the first character.
46                                 scanner.unread();
47                                 for (int j= i-1; j > 0; j--)
48                                         scanner.unread();
49                                 return false;
50                         }
51                 }
52                 return true;
53         }
54         
55         /*
56          * @see IRule#evaluate(ICharacterScanner)
57          * @since 2.0
58          */
59         public IToken evaluate(ICharacterScanner scanner) {
60                 int c;
61                 if ((c = scanner.read()) != '[') {
62                         if ((c != 'h' || ( !sequenceDetected(scanner, "http://".toCharArray(), false) && !sequenceDetected(scanner, "https://".toCharArray(), false) ))
63                                         && (c != 'f' || !sequenceDetected(scanner, "ftp://".toCharArray(), false)) ) {
64                                 // Not even a non-standard link
65                                 scanner.unread();
66                                 return Token.UNDEFINED;
67                         }
68                         
69                         //+ preventing NPE (Non-standard link should not be below as comment above suggests) by Paul Verest
70                         if (fDelimiters == null) {
71                                 scanner.unread();
72                                 return Token.UNDEFINED;
73                         }
74                         
75                         // Non-standard link
76                         while ((c = scanner.read()) != ICharacterScanner.EOF && !Character.isWhitespace(c)) {
77                                 for (int i = 0; i < fDelimiters.length; i++) {
78                                         if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) {
79                                                 return fToken;
80                                         }
81                                 }
82                         }
83                         return fToken;
84                 }
85                 if (fDelimiters == null) {
86                         fDelimiters = scanner.getLegalLineDelimiters();
87                 }
88                 int readCount = 1;
89                 
90                 // Find '](' and then find ')'
91                 boolean sequenceFound = false;
92                 int delimiterFound = 0;
93                 while ((c = scanner.read()) != ICharacterScanner.EOF && delimiterFound < 2) {
94                         readCount++;
95                         if ( !sequenceFound && c == ']') {
96                                 c = scanner.read();
97                                 if (c == '(') {
98                                         readCount++;
99                                         sequenceFound = true;
100                                 } else {
101                                         scanner.unread();
102                                 }
103                         } else if (c == ')') { // '](' is already found
104                                 return fToken;
105                         }
106                         
107                         int i;
108                         for (i = 0; i < fDelimiters.length; i++) {
109                                 if (c == fDelimiters[i][0] && sequenceDetected(scanner, fDelimiters[i], true)) {
110                                         delimiterFound ++;
111                                         break;
112                                 }       
113                         }
114                         if (i == fDelimiters.length)
115                                 delimiterFound = 0;
116                 }
117                 
118                 for (; readCount > 0; readCount--)
119                         scanner.unread();
120                 return Token.UNDEFINED;
121         }
122         
123 }