* Added browser like links (Ctrl+Mouseclick on identifier; same as F3 shortcut)
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / ui / text / JavaWordIterator.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2004 IBM Corporation 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 API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.ui.text;
12
13 import java.text.BreakIterator;
14 import java.text.CharacterIterator;
15
16 import org.eclipse.jface.text.Assert;
17
18
19 /**
20  * Breaks java text into word starts, also stops at line start and end. No 
21  * direction dependency.
22  *  
23  * @since 3.0
24  */
25 public class JavaWordIterator extends BreakIterator {
26         
27         /** 
28          * The underlying java break iterator. It returns all breaks, including
29          * before and after every whitespace.
30          */
31         private JavaBreakIterator fIterator;
32         /** The current index for the stateful operations. */
33         private int fIndex;
34         
35         /**
36          * Creates a new word iterator.
37          */
38         public JavaWordIterator() {
39                 fIterator= new JavaBreakIterator();
40                 first();
41         }
42
43         /*
44          * @see java.text.BreakIterator#first()
45          */
46         public int first() {
47                 fIndex= fIterator.first();
48                 return fIndex;
49         }
50
51         /*
52          * @see java.text.BreakIterator#last()
53          */
54         public int last() {
55                 fIndex= fIterator.last();
56                 return fIndex;
57         }
58
59         /*
60          * @see java.text.BreakIterator#next(int)
61          */
62         public int next(int n) {
63                 int next= 0;
64                 while (--n > 0 && next != DONE) {
65                         next= next();
66                 }
67                 return next;
68         }
69
70         /*
71          * @see java.text.BreakIterator#next()
72          */
73         public int next() {
74                 fIndex= following(fIndex);
75                 return fIndex;
76         }
77
78         /*
79          * @see java.text.BreakIterator#previous()
80          */
81         public int previous() {
82                 fIndex= preceding(fIndex);
83                 return fIndex;
84         }
85         
86         
87         /*
88          * @see java.text.BreakIterator#preceding(int)
89          */
90         public int preceding(int offset) {
91                 int first= fIterator.preceding(offset);
92                 if (isWhitespace(first, offset)) {
93                         int second= fIterator.preceding(first);
94                         if (second != DONE && !isDelimiter(second, first))
95                                 return second;
96                 }
97                 return first;
98         }
99
100         /*
101          * @see java.text.BreakIterator#following(int)
102          */
103         public int following(int offset) {
104                 int first= fIterator.following(offset);
105                 if (eatFollowingWhitespace(offset, first)) {
106                         int second= fIterator.following(first);
107                         if (isWhitespace(first, second))
108                                 return second;
109                 }
110                 return first;
111         }
112         
113         private boolean eatFollowingWhitespace(int offset, int exclusiveEnd) {
114                 if (exclusiveEnd == DONE || offset == DONE)
115                         return false;
116                 
117                 if (isWhitespace(offset, exclusiveEnd))
118                         return false;
119                 if (isDelimiter(offset, exclusiveEnd))
120                         return false;
121                 
122                 return true;
123         }
124         
125         /**
126          * Returns <code>true</code> if the given sequence into the underlying text
127          * represents a delimiter, <code>false</code> otherwise.
128          * 
129          * @param offset the offset
130          * @param exclusiveEnd the end offset
131          * @return <code>true</code> if the given range is a delimiter
132          */
133         private boolean isDelimiter(int offset, int exclusiveEnd) {
134                 if (exclusiveEnd == DONE || offset == DONE)
135                         return false;
136                 
137                 Assert.isTrue(offset >= 0);
138                 Assert.isTrue(exclusiveEnd <= getText().getEndIndex());
139                 Assert.isTrue(exclusiveEnd > offset);
140                 
141                 CharSequence seq= fIterator.fText;
142                 
143                 while (offset < exclusiveEnd) {
144                         char ch= seq.charAt(offset);
145                         if (ch != '\n' && ch != '\r')
146                                 return false;
147                         offset++;
148                 }
149                 
150                 return true;
151         }
152
153         /**
154          * Returns <code>true</code> if the given sequence into the underlying text
155          * represents whitespace, but not a delimiter, <code>false</code> otherwise.
156          * 
157          * @param offset the offset
158          * @param exclusiveEnd the end offset
159          * @return <code>true</code> if the given range is whitespace
160          */
161         private boolean isWhitespace(int offset, int exclusiveEnd) {
162                 if (exclusiveEnd == DONE || offset == DONE)
163                         return false;
164                 
165                 Assert.isTrue(offset >= 0);
166                 Assert.isTrue(exclusiveEnd <= getText().getEndIndex());
167                 Assert.isTrue(exclusiveEnd > offset);
168                 
169                 CharSequence seq= fIterator.fText;
170                 
171                 while (offset < exclusiveEnd) {
172                         char ch= seq.charAt(offset);
173                         if (!Character.isWhitespace(ch))
174                                 return false;
175                         if (ch == '\n' || ch == '\r')
176                                 return false;
177                         offset++;
178                 }
179                 
180                 return true;
181         }
182
183         /*
184          * @see java.text.BreakIterator#current()
185          */
186         public int current() {
187                 return fIndex;
188         }
189
190         /*
191          * @see java.text.BreakIterator#getText()
192          */
193         public CharacterIterator getText() {
194                 return fIterator.getText();
195         }
196         
197         /**
198          * Sets the text as <code>CharSequence</code>.
199          * @param newText the new text
200          */
201         public void setText(CharSequence newText) {
202                 fIterator.setText(newText);
203                 first();
204         }
205
206         /*
207          * @see java.text.BreakIterator#setText(java.text.CharacterIterator)
208          */
209         public void setText(CharacterIterator newText) {
210                 fIterator.setText(newText);
211                 first();
212         }
213         
214         /*
215          * @see java.text.BreakIterator#setText(java.lang.String)
216          */
217         public void setText(String newText) {
218                 setText((CharSequence) newText);
219         }
220
221 }