001: /*
002: * BracketIndentRule.java
003: * :tabSize=8:indentSize=8:noTabs=false:
004: * :folding=explicit:collapseFolds=1:
005: *
006: * Copyright (C) 2005 Slava Pestov
007: *
008: * This program is free software; you can redistribute it and/or
009: * modify it under the terms of the GNU General Public License
010: * as published by the Free Software Foundation; either version 2
011: * of the License, or any later version.
012: *
013: * This program is distributed in the hope that it will be useful,
014: * but WITHOUT ANY WARRANTY; without even the implied warranty of
015: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016: * GNU General Public License for more details.
017: *
018: * You should have received a copy of the GNU General Public License
019: * along with this program; if not, write to the Free Software
020: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
021: */
022:
023: package org.gjt.sp.jedit.indent;
024:
025: import javax.swing.text.Segment;
026: import org.gjt.sp.jedit.buffer.JEditBuffer;
027: import org.gjt.sp.jedit.syntax.Token;
028: import org.gjt.sp.jedit.syntax.TokenHandler;
029: import org.gjt.sp.jedit.syntax.TokenMarker;
030:
031: /**
032: * @author Slava Pestov
033: * @version $Id: BracketIndentRule.java 9524 2007-05-10 14:51:01Z k_satoda $
034: */
035: public abstract class BracketIndentRule implements IndentRule {
036: //{{{ BracketIndentRule constructor
037: public BracketIndentRule(char openBracket, char closeBracket) {
038: this .openBracket = openBracket;
039: this .closeBracket = closeBracket;
040: } //}}}
041:
042: //{{{ Brackets class
043: public static class Brackets {
044: int openCount;
045: int closeCount;
046: } //}}}
047:
048: //{{{ getBrackets() method
049: /**
050: * @deprecated
051: * Use {@link #getBrackets(JEditBuffer,int,int,int)} instead.
052: * Brackets in comments or literals should be ignored for indent.
053: * But it can't be done without syntax parsing of a buffer.
054: */
055: @Deprecated
056: public Brackets getBrackets(String line) {
057: Brackets brackets = new Brackets();
058:
059: for (int i = 0; i < line.length(); i++) {
060: char ch = line.charAt(i);
061: if (ch == openBracket) {
062: /* Don't increase indent when we see
063: an explicit fold. */
064: if (line.length() - i >= 3) {
065: if (line.substring(i, i + 3).equals("{{{")) /* }}} */
066: {
067: i += 2;
068: continue;
069: }
070: }
071: brackets.openCount++;
072: } else if (ch == closeBracket) {
073: if (brackets.openCount != 0)
074: brackets.openCount--;
075: else
076: brackets.closeCount++;
077: }
078: }
079:
080: return brackets;
081: } //}}}
082:
083: //{{{ getBrackets() method
084: public Brackets getBrackets(JEditBuffer buffer, int lineIndex) {
085: return getBrackets(buffer, lineIndex, 0, buffer
086: .getLineLength(lineIndex));
087: } //}}}
088:
089: //{{{ getBrackets() method
090: public Brackets getBrackets(JEditBuffer buffer, int lineIndex,
091: int begin, int end) {
092: LineScanner scanner = new LineScanner(begin, end);
093: buffer.markTokens(lineIndex, scanner);
094: return scanner.result;
095: } //}}}
096:
097: //{{{ toString() method
098: public String toString() {
099: return getClass().getName() + "[" + openBracket + ","
100: + closeBracket + "]";
101: } //}}}
102:
103: protected char openBracket, closeBracket;
104:
105: //{{{ class LineScanner
106: private class LineScanner implements TokenHandler {
107: public final Brackets result;
108:
109: private int scannedIndex;
110: private final int beginIndex;
111: private final int endIndex;
112:
113: public LineScanner(int begin, int end) {
114: this .result = new Brackets();
115: this .scannedIndex = 0;
116: this .beginIndex = begin;
117: this .endIndex = end;
118: }
119:
120: boolean rejectsToken(byte id) {
121: // Rejects comments and literals.
122: // Accepts all others.
123: switch (id) {
124: case Token.COMMENT1:
125: case Token.COMMENT2:
126: case Token.COMMENT3:
127: case Token.COMMENT4:
128: case Token.LITERAL1:
129: case Token.LITERAL2:
130: case Token.LITERAL3:
131: case Token.LITERAL4:
132: return true;
133: default:
134: return false;
135: }
136: }
137:
138: private void scan(Segment seg, int offset, int length) {
139: int index = scannedIndex;
140: if (index >= endIndex) {
141: return;
142: }
143: if (index < beginIndex) {
144: int numToSkip = beginIndex - index;
145: if (numToSkip >= length) {
146: return;
147: }
148: offset += numToSkip;
149: length -= numToSkip;
150: index = beginIndex;
151: }
152: if (index + length > endIndex) {
153: length = endIndex - index;
154: }
155:
156: for (int i = 0; i < length; ++i) {
157: char c = seg.array[seg.offset + offset + i];
158: if (c == openBracket) {
159: result.openCount++;
160: } else if (c == closeBracket) {
161: if (result.openCount != 0)
162: result.openCount--;
163: else
164: result.closeCount++;
165: }
166: }
167: }
168:
169: public void handleToken(Segment seg, byte id, int offset,
170: int length, TokenMarker.LineContext context) {
171: if (!rejectsToken(id)) {
172: scan(seg, offset, length);
173: }
174: scannedIndex += length;
175: }
176:
177: public void setLineContext(TokenMarker.LineContext lineContext) {
178: }
179: } //}}}
180: }
|