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