initial quantum version
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / PHPPairMatcher.java
1 package net.sourceforge.phpdt.internal.ui.text;
2
3 /*
4  * (c) Copyright IBM Corp. 2000, 2001.
5  * All Rights Reserved.
6  */
7
8 import java.io.IOException;
9
10 import org.eclipse.jface.text.BadLocationException;
11 import org.eclipse.jface.text.IDocument;
12 import org.eclipse.jface.text.IRegion;
13 import org.eclipse.jface.text.Region;
14 import org.eclipse.jface.text.source.ICharacterPairMatcher;
15
16 /**
17  * Helper class for match pairs of characters.
18  */
19 public class PHPPairMatcher implements ICharacterPairMatcher {
20         
21         
22         public static final int LEFT=      1;
23         public static final int RIGHT= 2;
24
25         
26         protected char[] fPairs;
27         protected IDocument fDocument;
28         protected int fOffset;
29         
30         protected int fStartPos;
31         protected int fEndPos;
32         protected int fAnchor;
33         
34         protected PHPCodeReader fReader= new PHPCodeReader();
35         
36         
37         public PHPPairMatcher(char[] pairs) {
38                 fPairs= pairs;
39         }
40         
41         /*
42          * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear()
43          */
44         public void clear() {
45                 if (fReader != null) {
46                         try {
47                                 fReader.close();
48                         } catch (IOException x) {
49                                 // ignore
50                         }
51                 }
52         }
53         
54         public IRegion match(IDocument document, int offset) {
55
56                 fOffset= offset;
57
58                 if (fOffset < 0)
59                         return null;
60
61                 fDocument= document;
62
63                 if (matchPairsAt() && fStartPos != fEndPos)
64                         return new Region(fStartPos, fEndPos - fStartPos + 1);
65                         
66                 return null;
67         }
68         
69         public int getAnchor() {
70                 return fAnchor;
71         }
72         
73         public void dispose() {
74                 fDocument= null;
75                 if (fReader != null) {
76                         try {
77                                 fReader.close();
78                         } catch (IOException x) {
79                                 // ignore
80                         }
81                         fReader= null;
82                 }
83         }
84         
85         protected boolean matchPairsAt() {
86
87                 int i;
88                 int pairIndex1= fPairs.length;
89                 int pairIndex2= fPairs.length;
90
91                 fStartPos= -1;
92                 fEndPos= -1;
93
94                 // get the chars preceding and following the start position
95                 try {
96
97                         char prevChar= fDocument.getChar(Math.max(fOffset - 1, 0));
98                         char nextChar= fDocument.getChar(fOffset);
99
100                         // search for opening peer character next to the activation point
101                         for (i= 0; i < fPairs.length; i= i + 2) {
102                                 if (nextChar == fPairs[i]) {
103                                         fStartPos= fOffset;
104                                         pairIndex1= i;
105                                 } else if (prevChar == fPairs[i]) {
106                                         fStartPos= fOffset - 1;
107                                         pairIndex1= i;
108                                 }
109                         }
110                         
111                         // search for closing peer character next to the activation point
112                         for (i= 1; i < fPairs.length; i= i + 2) {
113                                 if (prevChar == fPairs[i]) {
114                                         fEndPos= fOffset - 1;
115                                         pairIndex2= i;
116                                 } else if (nextChar == fPairs[i]) {
117                                         fEndPos= fOffset;
118                                         pairIndex2= i;
119                                 }
120                         }
121
122                         if (fEndPos > -1) {
123                                 fAnchor= RIGHT;
124                                 fStartPos= searchForOpeningPeer(fEndPos, fPairs[pairIndex2 - 1], fPairs[pairIndex2], fDocument);
125                                 if (fStartPos > -1)
126                                         return true;
127                                 else
128                                         fEndPos= -1;
129                         }       else if (fStartPos > -1) {
130                                 fAnchor= LEFT;
131                                 fEndPos= searchForClosingPeer(fStartPos, fPairs[pairIndex1], fPairs[pairIndex1 + 1], fDocument);
132                                 if (fEndPos > -1)
133                                         return true;
134                                 else
135                                         fStartPos= -1;
136                         }
137
138                 } catch (BadLocationException x) {
139                 } catch (IOException x) {
140                 }
141
142                 return false;
143         }
144         
145         protected int searchForClosingPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException {
146                 
147                 fReader.configureForwardReader(document, offset + 1, document.getLength(), true, true);
148                 
149                 int stack= 1;
150                 int c= fReader.read();
151                 while (c != PHPCodeReader.EOF) {
152                         if (c == openingPeer && c != closingPeer)
153                                 stack++;
154                         else if (c == closingPeer)
155                                 stack--;
156                                 
157                         if (stack == 0)
158                                 return fReader.getOffset();
159                                 
160                         c= fReader.read();
161                 }
162                 
163                 return  -1;
164         }
165         
166         protected int searchForOpeningPeer(int offset, int openingPeer, int closingPeer, IDocument document) throws IOException {
167                 
168                 fReader.configureBackwardReader(document, offset, true, true);
169                 
170                 int stack= 1;
171                 int c= fReader.read();
172                 while (c != PHPCodeReader.EOF) {
173                         if (c == closingPeer && c != openingPeer)
174                                 stack++;
175                         else if (c == openingPeer)
176                                 stack--;
177                                 
178                         if (stack == 0)
179                                 return fReader.getOffset();
180                                 
181                         c= fReader.read();
182                 }
183                 
184                 return -1;
185         }
186 }