1c55ba9ad5899663afeff2bf56a5cfd44c790dc5
[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  * Breaks java text into word starts, also stops at line start and end. No
20  * direction dependency.
21  * 
22  * @since 3.0
23  */
24 public class JavaWordIterator extends BreakIterator {
25
26         /**
27          * The underlying java break iterator. It returns all breaks, including
28          * before and after every whitespace.
29          */
30         private JavaBreakIterator fIterator;
31
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          * @see java.text.BreakIterator#preceding(int)
88          */
89         public int preceding(int offset) {
90                 int first = fIterator.preceding(offset);
91                 if (isWhitespace(first, offset)) {
92                         int second = fIterator.preceding(first);
93                         if (second != DONE && !isDelimiter(second, first))
94                                 return second;
95                 }
96                 return first;
97         }
98
99         /*
100          * @see java.text.BreakIterator#following(int)
101          */
102         public int following(int offset) {
103                 int first = fIterator.following(offset);
104                 if (eatFollowingWhitespace(offset, first)) {
105                         int second = fIterator.following(first);
106                         if (isWhitespace(first, second))
107                                 return second;
108                 }
109                 return first;
110         }
111
112         private boolean eatFollowingWhitespace(int offset, int exclusiveEnd) {
113                 if (exclusiveEnd == DONE || offset == DONE)
114                         return false;
115
116                 if (isWhitespace(offset, exclusiveEnd))
117                         return false;
118                 if (isDelimiter(offset, exclusiveEnd))
119                         return false;
120
121                 return true;
122         }
123
124         /**
125          * Returns <code>true</code> if the given sequence into the underlying
126          * text represents a delimiter, <code>false</code> otherwise.
127          * 
128          * @param offset
129          *            the offset
130          * @param exclusiveEnd
131          *            the end offset
132          * @return <code>true</code> if the given range is a delimiter
133          */
134         private boolean isDelimiter(int offset, int exclusiveEnd) {
135                 if (exclusiveEnd == DONE || offset == DONE)
136                         return false;
137
138                 Assert.isTrue(offset >= 0);
139                 Assert.isTrue(exclusiveEnd <= getText().getEndIndex());
140                 Assert.isTrue(exclusiveEnd > offset);
141
142                 CharSequence seq = fIterator.fText;
143
144                 while (offset < exclusiveEnd) {
145                         char ch = seq.charAt(offset);
146                         if (ch != '\n' && ch != '\r')
147                                 return false;
148                         offset++;
149                 }
150
151                 return true;
152         }
153
154         /**
155          * Returns <code>true</code> if the given sequence into the underlying
156          * text represents whitespace, but not a delimiter, <code>false</code>
157          * otherwise.
158          * 
159          * @param offset
160          *            the offset
161          * @param exclusiveEnd
162          *            the end offset
163          * @return <code>true</code> if the given range is whitespace
164          */
165         private boolean isWhitespace(int offset, int exclusiveEnd) {
166                 if (exclusiveEnd == DONE || offset == DONE)
167                         return false;
168
169                 Assert.isTrue(offset >= 0);
170                 Assert.isTrue(exclusiveEnd <= getText().getEndIndex());
171                 Assert.isTrue(exclusiveEnd > offset);
172
173                 CharSequence seq = fIterator.fText;
174
175                 while (offset < exclusiveEnd) {
176                         char ch = seq.charAt(offset);
177                         if (!Character.isWhitespace(ch))
178                                 return false;
179                         if (ch == '\n' || ch == '\r')
180                                 return false;
181                         offset++;
182                 }
183
184                 return true;
185         }
186
187         /*
188          * @see java.text.BreakIterator#current()
189          */
190         public int current() {
191                 return fIndex;
192         }
193
194         /*
195          * @see java.text.BreakIterator#getText()
196          */
197         public CharacterIterator getText() {
198                 return fIterator.getText();
199         }
200
201         /**
202          * Sets the text as <code>CharSequence</code>.
203          * 
204          * @param newText
205          *            the new text
206          */
207         public void setText(CharSequence newText) {
208                 fIterator.setText(newText);
209                 first();
210         }
211
212         /*
213          * @see java.text.BreakIterator#setText(java.text.CharacterIterator)
214          */
215         public void setText(CharacterIterator newText) {
216                 fIterator.setText(newText);
217                 first();
218         }
219
220         /*
221          * @see java.text.BreakIterator#setText(java.lang.String)
222          */
223         public void setText(String newText) {
224                 setText((CharSequence) newText);
225         }
226
227 }