1 package net.sourceforge.phpdt.internal.ui.text;
4 * (c) Copyright IBM Corp. 2000, 2001.
8 import java.io.IOException;
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;
17 * Helper class for match pairs of characters.
19 public class PHPPairMatcher implements ICharacterPairMatcher {
20 protected char[] fPairs; // Holds the brace pairs
22 protected IDocument fDocument;
24 protected int fOffset; // The current text position from which we search
25 protected int nPosOpening; // The position of the opening brace
26 protected int nPosClosing; // The position of the closing brace
27 protected int fAnchor;
29 protected PHPCodeReader fReader = new PHPCodeReader();
33 * @param pairs The array of opening and closing braces we need for searching the brace matching
36 public PHPPairMatcher(char[] pairs) {
41 * @see org.eclipse.jface.text.source.ICharacterPairMatcher#clear()
44 if (fReader != null) {
47 } catch (IOException x) {
54 * Try to find a matching pair of opening and closing braces
56 * @return Returns a region if a matching pair was found.
58 public IRegion match(IDocument document, int offset) {
67 if (matchPairsAt ()) { // If we found a pair of opening and closing braces
68 return new Region (nPosOpening, nPosClosing - nPosOpening + 1);
74 public int getAnchor() {
78 public void dispose() {
80 if (fReader != null) {
83 } catch (IOException x) {
91 * Take the character from the current text position, checks for opening or closing braces and search for
92 * the corresponding opening or closing brace
94 * @return True if a pair was found
96 protected boolean matchPairsAt() {
98 int nIndexOpen = fPairs.length; // Opening index
99 int nIndexClose = fPairs.length;
100 char cCurrentChar; // The character from the current text position
101 char cPrevChar; // The character from the previouis text position, just
102 // for the case the user pointed the cursor after the opening or closing brace
107 // get the chars preceding and following the start position
109 cCurrentChar = fDocument.getChar (fOffset);
110 cPrevChar = fDocument.getChar (Math.max (fOffset - 1, 0));
112 // search for opening peer character next to the activation point
113 for (i = 0; i < fPairs.length; i = i + 2) { // The opening brace is on even indexes
114 if (cCurrentChar == fPairs[i]) { // If the current character matches an opening brace
115 nPosOpening = fOffset; // Remember the character position
116 nIndexOpen = i; // and remember the opening brace for which we search the closing one
118 else if (cPrevChar == fPairs[i]) { // If the current character is not an opening, but the previous character is an opening brace
119 nPosOpening = fOffset - 1; // Remember the character position
120 nIndexOpen = i; // and remember the opening brace for which we search the closing one
124 // search for closing peer character next to the activation point
126 if (nPosOpening < 0) { // If we didn't find an opening brace
127 for (i = 1; i < fPairs.length; i = i + 2) { // The closing brace is on odd indexes
128 if (cCurrentChar == fPairs[i]) { // If the current character matches an closing brace
129 nPosClosing = fOffset; // Remember the character position
130 nIndexClose = i; // and remember the opening brace for which we search the closing one
132 else if (cPrevChar == fPairs[i]) { // If the current character is not an opening, but the previous character is an opening brace
133 nPosClosing = fOffset - 1; // Remember the character position
134 nIndexClose = i; // and remember the opening brace for which we search the closing one
139 if (nPosClosing > -1) { // If we found a closing brace on current position (or before)
141 nPosOpening = searchForOpeningPeer (nPosClosing, fPairs[nIndexClose - 1], fPairs[nIndexClose], fDocument);
143 return (nPosOpening > -1); // If we found a opening brace, return true
145 else if (nPosOpening > -1) { // If we found a opening brace on current position (or before)
147 nPosClosing = searchForClosingPeer (nPosOpening, fPairs[nIndexOpen], fPairs[nIndexOpen + 1], fDocument);
149 return (nPosClosing > -1); // If we found an closing brace for this opening brace return true
152 catch (BadLocationException x) {
154 catch (IOException x) {
162 * @param offset The search start position
163 * @param openingPeer The opening brace we had found
164 * @param closingPeer The closing brace we search for
165 * @param document The document we currently are in
169 * @throws IOException
171 protected int searchForClosingPeer (int offset, char openingPeer,
172 char closingPeer, IDocument document) throws IOException {
173 fReader.configureForwardReader (document, offset + 1, document.getLength(), true, true);
175 int stack = 1; // As we have already the opening brace
176 int c = fReader.read (); // Read character on position one after the opening brace
178 while (c != PHPCodeReader.EOF) { // As long as we are not at the end
179 if ((c == openingPeer) && // If character is opening brace again
180 (c != closingPeer)) { // and not a closing brace (how could it be?)
181 stack++; // put it on stack
183 else if (c == closingPeer) { // If it's a closing brace
184 stack--; // Decrement level counter
187 if (stack == 0) { // If we found the matching closing brace
188 return fReader.getOffset (); // return the position of this closing brace
191 c = fReader.read (); // Read the next character
199 * @param offset The search start position
200 * @param openingPeer The opening brace we search for
201 * @param closingPeer The closing brace we search for
202 * @param document The document we currently are in
206 * @throws IOException
208 protected int searchForOpeningPeer (int offset, char openingPeer,
209 char closingPeer, IDocument document) throws IOException {
210 fReader.configureBackwardReader(document, offset, true, true);
212 int stack = 1; // As we have already the opening brace
213 int c = fReader.read (); // Read character on position one before the closing brace
215 while (c != PHPCodeReader.EOF) { // As long as we are not at the start of text
216 if ((c == closingPeer) && // If character is closing brace again
217 (c != openingPeer)) { // and not a opening brace (how could it be?)
218 stack++; // put it on stack
220 else if (c == openingPeer) { // If it's a opening brace
221 stack--; // Decrement level counter
224 if (stack == 0) { // If we found the matching closing brace
225 return fReader.getOffset (); // return the position of this closing brace
228 c = fReader.read (); // Read the previous character