001: /*
002: * TextUtilities.java - Utility functions used by the text area classes
003: * Copyright (C) 1999 Slava Pestov
004: *
005: * You may use and modify this package for any purpose. Redistribution is
006: * permitted, in both source and binary form, provided that this notice
007: * remains intact in all source distributions of this package.
008: */
009:
010: package org.syntax.jedit;
011:
012: import javax.swing.text.*;
013:
014: /**
015: * Class with several utility functions used by the text area component.
016: * @author Slava Pestov
017: * @version $Id: TextUtilities.java 3074 2004-11-08 04:24:58Z bquig $
018: */
019: public class TextUtilities {
020: /**
021: * Returns the offset of the bracket matching the one at the
022: * specified offset of the document, or -1 if the bracket is
023: * unmatched (or if the character is not a bracket).
024: * @param doc The document
025: * @param offset The offset
026: * @exception BadLocationException If an out-of-bounds access
027: * was attempted on the document text
028: */
029: public static int findMatchingBracket(Document doc, int offset)
030: throws BadLocationException {
031: if (doc.getLength() == 0)
032: return -1;
033: char c = doc.getText(offset, 1).charAt(0);
034: char cprime; // c` - corresponding character
035: boolean direction; // true = back, false = forward
036:
037: switch (c) {
038: case '(':
039: cprime = ')';
040: direction = false;
041: break;
042: case ')':
043: cprime = '(';
044: direction = true;
045: break;
046: case '[':
047: cprime = ']';
048: direction = false;
049: break;
050: case ']':
051: cprime = '[';
052: direction = true;
053: break;
054: case '{':
055: cprime = '}';
056: direction = false;
057: break;
058: case '}':
059: cprime = '{';
060: direction = true;
061: break;
062: default:
063: return -1;
064: }
065:
066: int count;
067:
068: // How to merge these two cases is left as an exercise
069: // for the reader.
070:
071: // Go back or forward
072: if (direction) {
073: // Count is 1 initially because we have already
074: // `found' one closing bracket
075: count = 1;
076:
077: // Get text[0,offset-1];
078: String text = doc.getText(0, offset);
079:
080: // Scan backwards
081: for (int i = offset - 1; i >= 0; i--) {
082: // If text[i] == c, we have found another
083: // closing bracket, therefore we will need
084: // two opening brackets to complete the
085: // match.
086: char x = text.charAt(i);
087: if (x == c)
088: count++;
089:
090: // If text[i] == cprime, we have found a
091: // opening bracket, so we return i if
092: // --count == 0
093: else if (x == cprime) {
094: if (--count == 0)
095: return i;
096: }
097: }
098: } else {
099: // Count is 1 initially because we have already
100: // `found' one opening bracket
101: count = 1;
102:
103: // So we don't have to + 1 in every loop
104: offset++;
105:
106: // Number of characters to check
107: int len = doc.getLength() - offset;
108:
109: // Get text[offset+1,len];
110: String text = doc.getText(offset, len);
111:
112: // Scan forwards
113: for (int i = 0; i < len; i++) {
114: // If text[i] == c, we have found another
115: // opening bracket, therefore we will need
116: // two closing brackets to complete the
117: // match.
118: char x = text.charAt(i);
119:
120: if (x == c)
121: count++;
122:
123: // If text[i] == cprime, we have found an
124: // closing bracket, so we return i if
125: // --count == 0
126: else if (x == cprime) {
127: if (--count == 0)
128: return i + offset;
129: }
130: }
131: }
132:
133: // Nothing found
134: return -1;
135: }
136:
137: /**
138: * Locates the start of the word at the specified position.
139: * @param line The text
140: * @param pos The position
141: */
142: public static int findWordStart(String line, int pos,
143: String noWordSep) {
144: char ch = line.charAt(pos - 1);
145:
146: if (noWordSep == null)
147: noWordSep = "";
148: boolean selectNoLetter = (!Character.isLetterOrDigit(ch) && noWordSep
149: .indexOf(ch) == -1);
150:
151: int wordStart = 0;
152: for (int i = pos - 1; i >= 0; i--) {
153: ch = line.charAt(i);
154: if (selectNoLetter
155: ^ (!Character.isLetterOrDigit(ch) && noWordSep
156: .indexOf(ch) == -1)) {
157: wordStart = i + 1;
158: break;
159: }
160: }
161:
162: return wordStart;
163: }
164:
165: /**
166: * Locates the end of the word at the specified position.
167: * @param line The text
168: * @param pos The position
169: */
170: public static int findWordEnd(String line, int pos, String noWordSep) {
171: char ch = line.charAt(pos);
172:
173: if (noWordSep == null)
174: noWordSep = "";
175: boolean selectNoLetter = (!Character.isLetterOrDigit(ch) && noWordSep
176: .indexOf(ch) == -1);
177:
178: int wordEnd = line.length();
179: for (int i = pos; i < line.length(); i++) {
180: ch = line.charAt(i);
181: if (selectNoLetter
182: ^ (!Character.isLetterOrDigit(ch) && noWordSep
183: .indexOf(ch) == -1)) {
184: wordEnd = i;
185: break;
186: }
187: }
188: return wordEnd;
189: }
190: }
|