52bff9c6b0e1870f6f0e737174724673bea3bd04
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpeclipse / phpeditor / php / PHPDoubleClickSelector.java
1 /**********************************************************************
2 Copyright (c) 2000, 2002 IBM Corp. and others.
3 All rights reserved. This program and the accompanying materials
4 are made available under the terms of the Common Public License v1.0
5 which accompanies this distribution, and is available at
6 http://www.eclipse.org/legal/cpl-v10.html
7
8 Contributors:
9     IBM Corporation - Initial implementation
10     Klaus Hartlage - www.eclipseproject.de
11 **********************************************************************/
12 package net.sourceforge.phpeclipse.phpeditor.php;
13
14
15 import net.sourceforge.phpdt.internal.compiler.parser.Scanner;
16
17 import org.eclipse.jface.text.BadLocationException;
18 import org.eclipse.jface.text.IDocument;
19 import org.eclipse.jface.text.ITextDoubleClickStrategy;
20 import org.eclipse.jface.text.ITextViewer;
21
22 /**
23  * Double click strategy aware of PHP identifier syntax rules.
24  */
25 public class PHPDoubleClickSelector implements ITextDoubleClickStrategy {
26
27         protected ITextViewer fText;
28         protected int fPos;
29         protected int fStartPos;
30         protected int fEndPos;
31
32         protected static char[] fgBrackets = { '{', '}', '(', ')', '[', ']', '"', '"' };
33
34         /* 
35          * Create a PHPDoubleClickSelector.
36          */
37         public PHPDoubleClickSelector() {
38                 super();
39         }
40
41         /* (non-Javadoc)
42          * Method declared on ITextDoubleClickStrategy
43          */
44         public void doubleClicked(ITextViewer text) {
45
46                 fPos = text.getSelectedRange().x;
47
48                 if (fPos < 0)
49                         return;
50
51                 fText = text;
52
53                 if (!selectBracketBlock())
54                         selectWord();
55         }
56
57         /**
58          * Match the brackets at the current selection. Return true if successful,
59          * false otherwise.
60          */
61         protected boolean matchBracketsAt() {
62
63                 char prevChar, nextChar;
64
65                 int i;
66                 int bracketIndex1 = fgBrackets.length;
67                 int bracketIndex2 = fgBrackets.length;
68
69                 fStartPos = -1;
70                 fEndPos = -1;
71
72                 // get the chars preceding and following the start position
73                 try {
74
75                         IDocument doc = fText.getDocument();
76
77                         prevChar = doc.getChar(fPos - 1);
78                         nextChar = doc.getChar(fPos);
79
80                         // is the char either an open or close bracket?
81                         for (i = 0; i < fgBrackets.length; i = i + 2) {
82                                 if (prevChar == fgBrackets[i]) {
83                                         fStartPos = fPos - 1;
84                                         bracketIndex1 = i;
85                                 }
86                         }
87                         for (i = 1; i < fgBrackets.length; i = i + 2) {
88                                 if (nextChar == fgBrackets[i]) {
89                                         fEndPos = fPos;
90                                         bracketIndex2 = i;
91                                 }
92                         }
93
94                         if (fStartPos > -1 && bracketIndex1 < bracketIndex2) {
95                                 fEndPos = searchForClosingBracket(fStartPos, prevChar, fgBrackets[bracketIndex1 + 1], doc);
96                                 if (fEndPos > -1)
97                                         return true;
98                                 else
99                                         fStartPos = -1;
100                         } else if (fEndPos > -1) {
101                                 fStartPos = searchForOpenBracket(fEndPos, fgBrackets[bracketIndex2 - 1], nextChar, doc);
102                                 if (fStartPos > -1)
103                                         return true;
104                                 else
105                                         fEndPos = -1;
106                         }
107
108                 } catch (BadLocationException x) {
109                 }
110
111                 return false;
112         }
113
114         /**
115          * Select the word at the current selection. Return true if successful,
116          * false otherwise.
117          */
118         protected boolean matchWord() {
119
120                 IDocument doc = fText.getDocument();
121
122                 try {
123
124                         int pos = fPos;
125                         char c;
126
127                         while (pos >= 0) {
128                                 c = doc.getChar(pos);
129                                 if (!Scanner.isPHPIdentifierPart(c) && (c != '$')) {
130                                         break;
131                                 }
132                                 --pos;
133                         }
134
135                         fStartPos = pos;
136
137                         pos = fPos;
138                         int length = doc.getLength();
139
140                         while (pos < length) {
141                                 c = doc.getChar(pos);
142                                 if (!Scanner.isPHPIdentifierPart(c) && (c != '$'))
143                                         break;
144                                 ++pos;
145                         }
146
147                         fEndPos = pos;
148
149                         return true;
150
151                 } catch (BadLocationException x) {
152                 }
153
154                 return false;
155         }
156
157         /**
158          * Returns the position of the closing bracket after startPosition.
159          * @returns the location of the closing bracket.
160          * @param startPosition - the beginning position
161          * @param openBracket - the character that represents the open bracket
162          * @param closeBracket - the character that represents the close bracket
163          * @param document - the document being searched
164          */
165         protected int searchForClosingBracket(int startPosition, char openBracket, char closeBracket, IDocument document)
166                 throws BadLocationException {
167                 int stack = 1;
168                 int closePosition = startPosition + 1;
169                 int length = document.getLength();
170                 char nextChar;
171
172                 while (closePosition < length && stack > 0) {
173                         nextChar = document.getChar(closePosition);
174                         if (nextChar == openBracket && nextChar != closeBracket)
175                                 stack++;
176                         else if (nextChar == closeBracket)
177                                 stack--;
178                         closePosition++;
179                 }
180
181                 if (stack == 0)
182                         return closePosition - 1;
183                 else
184                         return -1;
185
186         }
187
188         /**
189          * Returns the position of the open bracket before startPosition.
190          * @returns the location of the starting bracket.
191          * @param startPosition - the beginning position
192          * @param openBracket - the character that represents the open bracket
193          * @param closeBracket - the character that represents the close bracket
194          * @param document - the document being searched
195          */
196         protected int searchForOpenBracket(int startPosition, char openBracket, char closeBracket, IDocument document)
197                 throws BadLocationException {
198                 int stack = 1;
199                 int openPos = startPosition - 1;
200                 char nextChar;
201
202                 while (openPos >= 0 && stack > 0) {
203                         nextChar = document.getChar(openPos);
204                         if (nextChar == closeBracket && nextChar != openBracket)
205                                 stack++;
206                         else if (nextChar == openBracket)
207                                 stack--;
208                         openPos--;
209                 }
210
211                 if (stack == 0)
212                         return openPos + 1;
213                 else
214                         return -1;
215         }
216
217         /**
218          * Select the area between the selected bracket and the closing bracket. Return
219          * true if successful.
220          */
221         protected boolean selectBracketBlock() {
222                 if (matchBracketsAt()) {
223
224                         if (fStartPos == fEndPos)
225                                 fText.setSelectedRange(fStartPos, 0);
226                         else
227                                 fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
228
229                         return true;
230                 }
231                 return false;
232         }
233
234         /**
235          * Select the word at the current selection. 
236          */
237         protected void selectWord() {
238                 if (matchWord()) {
239
240                         if (fStartPos == fEndPos)
241                                 fText.setSelectedRange(fStartPos, 0);
242                         else
243                                 fText.setSelectedRange(fStartPos + 1, fEndPos - fStartPos - 1);
244                 }
245         }
246 }