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   * @author Slava Pestov
18   * @version $Id$
19   */
20  public class TextUtilities
21  {
22  	/***
23  	 * Returns the offset of the bracket matching the one at the
24  	 * specified offset of the document, or -1 if the bracket is
25  	 * unmatched (or if the character is not a bracket).
26  	 * @param doc The document
27  	 * @param offset The offset
28  	 * @exception BadLocationException If an out-of-bounds access
29  	 * was attempted on the document text
30  	 */
31  	public static int findMatchingBracket(Document doc, int offset)
32  		throws BadLocationException
33  	{
34  		if(doc.getLength() == 0)
35  			return -1;
36  		char c = doc.getText(offset,1).charAt(0);
37  		char cprime; // c` - corresponding character
38  		boolean direction; // true = back, false = forward
39  
40  		switch(c)
41  		{
42  		case '(': cprime = ')'; direction = false; break;
43  		case ')': cprime = '('; direction = true; break;
44  		case '[': cprime = ']'; direction = false; break;
45  		case ']': cprime = '['; direction = true; break;
46  		case '{': cprime = '}'; direction = false; break;
47  		case '}': cprime = '{'; direction = true; break;
48  		default: return -1;
49  		}
50  
51  		int count;
52  
53  		// How to merge these two cases is left as an exercise
54  		// for the reader.
55  
56  		// Go back or forward
57  		if(direction)
58  		{
59  			// Count is 1 initially because we have already
60  			// `found' one closing bracket
61  			count = 1;
62  
63  			// Get text[0,offset-1];
64  			String text = doc.getText(0,offset);
65  
66  			// Scan backwards
67  			for(int i = offset - 1; i >= 0; i--)
68  			{
69  				// If text[i] == c, we have found another
70  				// closing bracket, therefore we will need
71  				// two opening brackets to complete the
72  				// match.
73  				char x = text.charAt(i);
74  				if(x == c)
75  					count++;
76  
77  				// If text[i] == cprime, we have found a
78  				// opening bracket, so we return i if
79  				// --count == 0
80  				else if(x == cprime)
81  				{
82  					if(--count == 0)
83  						return i;
84  				}
85  			}
86  		}
87  		else
88  		{
89  			// Count is 1 initially because we have already
90  			// `found' one opening bracket
91  			count = 1;
92  
93  			// So we don't have to + 1 in every loop
94  			offset++;
95  
96  			// Number of characters to check
97  			int len = doc.getLength() - offset;
98  
99  			// Get text[offset+1,len];
100 			String text = doc.getText(offset,len);
101 
102 			// Scan forwards
103 			for(int i = 0; i < len; i++)
104 			{
105 				// If text[i] == c, we have found another
106 				// opening bracket, therefore we will need
107 				// two closing brackets to complete the
108 				// match.
109 				char x = text.charAt(i);
110 
111 				if(x == c)
112 					count++;
113 
114 				// If text[i] == cprime, we have found an
115 				// closing bracket, so we return i if
116 				// --count == 0
117 				else if(x == cprime)
118 				{
119 					if(--count == 0)
120 						return i + offset;
121 				}
122 			}
123 		}
124 
125 		// Nothing found
126 		return -1;
127 	}
128 
129 	/***
130 	 * Locates the start of the word at the specified position.
131 	 * @param line The text
132 	 * @param pos The position
133 	 */
134 	public static int findWordStart(String line, int pos, String noWordSep)
135 	{
136 		char ch = line.charAt(pos - 1);
137 
138 		if(noWordSep == null)
139 			noWordSep = "";
140 		boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
141 			&& noWordSep.indexOf(ch) == -1);
142 
143 		int wordStart = 0;
144 		for(int i = pos - 1; i >= 0; i--)
145 		{
146 			ch = line.charAt(i);
147 			if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
148 				noWordSep.indexOf(ch) == -1))
149 			{
150 				wordStart = i + 1;
151 				break;
152 			}
153 		}
154 
155 		return wordStart;
156 	}
157 
158 	/***
159 	 * Locates the end of the word at the specified position.
160 	 * @param line The text
161 	 * @param pos The position
162 	 */
163 	public static int findWordEnd(String line, int pos, String noWordSep)
164 	{
165 		char ch = line.charAt(pos);
166 
167 		if(noWordSep == null)
168 			noWordSep = "";
169 		boolean selectNoLetter = (!Character.isLetterOrDigit(ch)
170 			&& noWordSep.indexOf(ch) == -1);
171 
172 		int wordEnd = line.length();
173 		for(int i = pos; i < line.length(); i++)
174 		{
175 			ch = line.charAt(i);
176 			if(selectNoLetter ^ (!Character.isLetterOrDigit(ch) &&
177 				noWordSep.indexOf(ch) == -1))
178 			{
179 				wordEnd = i;
180 				break;
181 			}
182 		}
183 		return wordEnd;
184 	}
185 }