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