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