001: /*******************************************************************************
002: * Copyright (c) 2006 IBM Corporation and others.
003: * All rights reserved. This program and the accompanying materials
004: * are made available under the terms of the Eclipse Public License v1.0
005: * which accompanies this distribution, and is available at
006: * http://www.eclipse.org/legal/epl-v10.html
007: *
008: * Contributors:
009: * IBM Corporation - initial API and implementation
010: *******************************************************************************/package org.eclipse.pde.internal.ui.editor.contentassist.display;
011:
012: import java.io.IOException;
013: import java.io.Reader;
014:
015: /**
016: * Reads the text contents from a reader and computes for each character
017: * a potential substitution. The substitution may eat more characters than
018: * only the one passed into the computation routine.
019: */
020: abstract class SubstitutionTextReader extends SingleCharReader {
021:
022: protected static final String LINE_DELIM = System.getProperty(
023: "line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$
024:
025: private Reader fReader;
026: private boolean fWasWhiteSpace;
027: private int fCharAfterWhiteSpace;
028:
029: /**
030: * Tells whether white space characters are skipped.
031: */
032: private boolean fSkipWhiteSpace = true;
033:
034: private boolean fReadFromBuffer;
035: private StringBuffer fBuffer;
036: private int fIndex;
037:
038: protected SubstitutionTextReader(Reader reader) {
039: fReader = reader;
040: fBuffer = new StringBuffer();
041: fIndex = 0;
042: fReadFromBuffer = false;
043: fCharAfterWhiteSpace = -1;
044: fWasWhiteSpace = true;
045: }
046:
047: /**
048: * Computes the substitution for the given character and if necessary
049: * subsequent characters. Implementation should use <code>nextChar</code>
050: * to read subsequent characters.
051: *
052: * @param c the character to be substituted
053: * @return the substitution for <code>c</code>
054: * @throws IOException in case computing the substitution fails
055: */
056: protected abstract String computeSubstitution(int c)
057: throws IOException;
058:
059: /**
060: * Returns the internal reader.
061: *
062: * @return the internal reader
063: */
064: protected Reader getReader() {
065: return fReader;
066: }
067:
068: /**
069: * Returns the next character.
070: * @return the next character
071: * @throws IOException in case reading the character fails
072: */
073: protected int nextChar() throws IOException {
074: fReadFromBuffer = (fBuffer.length() > 0);
075: if (fReadFromBuffer) {
076: char ch = fBuffer.charAt(fIndex++);
077: if (fIndex >= fBuffer.length()) {
078: fBuffer.setLength(0);
079: fIndex = 0;
080: }
081: return ch;
082: }
083:
084: int ch = fCharAfterWhiteSpace;
085: if (ch == -1) {
086: ch = fReader.read();
087: }
088: if (fSkipWhiteSpace && Character.isWhitespace((char) ch)) {
089: do {
090: ch = fReader.read();
091: } while (Character.isWhitespace((char) ch));
092: if (ch != -1) {
093: fCharAfterWhiteSpace = ch;
094: return ' ';
095: }
096: } else {
097: fCharAfterWhiteSpace = -1;
098: }
099: return ch;
100: }
101:
102: /**
103: * @see Reader#read()
104: */
105: public int read() throws IOException {
106: int c;
107: do {
108:
109: c = nextChar();
110: while (!fReadFromBuffer) {
111: String s = computeSubstitution(c);
112: if (s == null)
113: break;
114: if (s.length() > 0)
115: fBuffer.insert(0, s);
116: c = nextChar();
117: }
118:
119: } while (fSkipWhiteSpace && fWasWhiteSpace && (c == ' '));
120: fWasWhiteSpace = (c == ' ' || c == '\r' || c == '\n');
121: return c;
122: }
123:
124: /**
125: * @see Reader#ready()
126: */
127: public boolean ready() throws IOException {
128: return fReader.ready();
129: }
130:
131: /**
132: * @see Reader#close()
133: */
134: public void close() throws IOException {
135: fReader.close();
136: }
137:
138: /**
139: * @see Reader#reset()
140: */
141: public void reset() throws IOException {
142: fReader.reset();
143: fWasWhiteSpace = true;
144: fCharAfterWhiteSpace = -1;
145: fBuffer.setLength(0);
146: fIndex = 0;
147: }
148:
149: protected final void setSkipWhitespace(boolean state) {
150: fSkipWhiteSpace = state;
151: }
152:
153: protected final boolean isSkippingWhitespace() {
154: return fSkipWhiteSpace;
155: }
156: }
|