View Javadoc

1   /*
2    * TextUtilities.java - Utility functions used by the text area classes
3    * Copyright (C) 1999 Slava Pestov
4    *
5    * You may use and modify this package for any purpose. Redistribution is
6    * permitted, in both source and binary form, provided that this notice
7    * remains intact in all source distributions of this package.
8    */
9   
10  package org.syntax.jedit;
11  
12  import javax.swing.text.BadLocationException;
13  import javax.swing.text.Document;
14  
15  /***
16   * Class with several utility functions used by the text area component.
17   * 
18   * @author Slava Pestov
19   * @version $Id$
20   */
21  public class TextUtilities
22  {
23  	/***
24  	 * Returns the offset of the bracket matching the one at the specified offset
25  	 * of the document, or -1 if the bracket is unmatched (or if the character is
26  	 * not a bracket).
27  	 * 
28  	 * @param doc
29  	 *           The document
30  	 * @param offset
31  	 *           The offset
32  	 * @exception BadLocationException
33  	 *               If an out-of-bounds access was attempted on the document
34  	 *               text
35  	 */
36  	public static int findMatchingBracket( Document doc, int offset ) throws BadLocationException
37  	{
38  		if( doc.getLength() == 0 )
39  			return -1;
40  		char c = doc.getText( offset, 1 ).charAt( 0 );
41  		char cprime; // c` - corresponding character
42  		boolean direction; // true = back, false = forward
43  
44  		switch( c )
45  		{
46  		case '(' :
47  			cprime = ')';
48  			direction = false;
49  			break;
50  		case ')' :
51  			cprime = '(';
52  			direction = true;
53  			break;
54  		case '[' :
55  			cprime = ']';
56  			direction = false;
57  			break;
58  		case ']' :
59  			cprime = '[';
60  			direction = true;
61  			break;
62  		case '{' :
63  			cprime = '}';
64  			direction = false;
65  			break;
66  		case '}' :
67  			cprime = '{';
68  			direction = true;
69  			break;
70  		default :
71  			return -1;
72  		}
73  
74  		int count;
75  
76  		// How to merge these two cases is left as an exercise
77  		// for the reader.
78  
79  		// Go back or forward
80  		if( direction )
81  		{
82  			// Count is 1 initially because we have already
83  			// `found' one closing bracket
84  			count = 1;
85  
86  			// Get text[0,offset-1];
87  			String text = doc.getText( 0, offset );
88  
89  			// Scan backwards
90  			for( int i = offset - 1; i >= 0; i-- )
91  			{
92  				// If text[i] == c, we have found another
93  				// closing bracket, therefore we will need
94  				// two opening brackets to complete the
95  				// match.
96  				char x = text.charAt( i );
97  				if( x == c )
98  					count++ ;
99  
100 				// If text[i] == cprime, we have found a
101 				// opening bracket, so we return i if
102 				// --count == 0
103 				else if( x == cprime )
104 				{
105 					if( --count == 0 )
106 						return i;
107 				}
108 			}
109 		}
110 		else
111 		{
112 			// Count is 1 initially because we have already
113 			// `found' one opening bracket
114 			count = 1;
115 
116 			// So we don't have to + 1 in every loop
117 			offset++ ;
118 
119 			// Number of characters to check
120 			int len = doc.getLength() - offset;
121 
122 			// Get text[offset+1,len];
123 			String text = doc.getText( offset, len );
124 
125 			// Scan forwards
126 			for( int i = 0; i < len; i++ )
127 			{
128 				// If text[i] == c, we have found another
129 				// opening bracket, therefore we will need
130 				// two closing brackets to complete the
131 				// match.
132 				char x = text.charAt( i );
133 
134 				if( x == c )
135 					count++ ;
136 
137 				// If text[i] == cprime, we have found an
138 				// closing bracket, so we return i if
139 				// --count == 0
140 				else if( x == cprime )
141 				{
142 					if( --count == 0 )
143 						return i + offset;
144 				}
145 			}
146 		}
147 
148 		// Nothing found
149 		return -1;
150 	}
151 
152 	/***
153 	 * Locates the start of the word at the specified position.
154 	 * 
155 	 * @param line
156 	 *           The text
157 	 * @param pos
158 	 *           The position
159 	 */
160 	public static int findWordStart( String line, int pos, String noWordSep )
161 	{
162 		char ch = line.charAt( pos - 1 );
163 
164 		if( noWordSep == null )
165 			noWordSep = "";
166 		boolean selectNoLetter = ( !Character.isLetterOrDigit( ch ) && noWordSep.indexOf( ch ) == -1 );
167 
168 		int wordStart = 0;
169 		for( int i = pos - 1; i >= 0; i-- )
170 		{
171 			ch = line.charAt( i );
172 			if( selectNoLetter ^ ( !Character.isLetterOrDigit( ch ) && noWordSep.indexOf( ch ) == -1 ) )
173 			{
174 				wordStart = i + 1;
175 				break;
176 			}
177 		}
178 
179 		return wordStart;
180 	}
181 
182 	/***
183 	 * Locates the end of the word at the specified position.
184 	 * 
185 	 * @param line
186 	 *           The text
187 	 * @param pos
188 	 *           The position
189 	 */
190 	public static int findWordEnd( String line, int pos, String noWordSep )
191 	{
192 		char ch = line.charAt( pos );
193 
194 		if( noWordSep == null )
195 			noWordSep = "";
196 		boolean selectNoLetter = ( !Character.isLetterOrDigit( ch ) && noWordSep.indexOf( ch ) == -1 );
197 
198 		int wordEnd = line.length();
199 		for( int i = pos; i < line.length(); i++ )
200 		{
201 			ch = line.charAt( i );
202 			if( selectNoLetter ^ ( !Character.isLetterOrDigit( ch ) && noWordSep.indexOf( ch ) == -1 ) )
203 			{
204 				wordEnd = i;
205 				break;
206 			}
207 		}
208 		return wordEnd;
209 	}
210 }