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